openfda-mcp-server
Server Details
Query FDA data on drugs, food, devices, and recalls via openFDA. STDIO or Streamable HTTP.
- Status
- Healthy
- Last Tested
- Transport
- Streamable HTTP
- URL
- Repository
- cyanheads/openfda-mcp-server
- GitHub Stars
- 4
- Server Listing
- @cyanheads/openfda-mcp-server
Available Tools
14 toolsopenfda_count_valuesOpenfda Count ValuesARead-onlyInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| count | Yes | Field to count. Append .exact for whole-phrase counting of free-text fields (e.g. "patient.reaction.reactionmeddrapt.exact"). Identifier fields openFDA already indexes as keywords (product_ndc, application_number, pma_number) must be counted bare — .exact on those is rejected as not countable. | |
| limit | No | Number of top terms to return (default 100, max 1000) | |
| search | No | Filter query to scope the count (e.g. patient.drug.medicinalproduct:"metformin"). Omit to count across every record in the endpoint. Double quotes, parentheses, and range brackets must balance, and the query must not end on a backslash — each is rejected before the request. | |
| endpoint | Yes | Full openFDA endpoint path (e.g. "drug/event", "device/classification") |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | The limit applied to the term list. |
| meta | No | Response metadata |
| error | No | Present when the call failed. Absent on success. |
| shown | No | Number of terms returned in this response. |
| notice | No | Guidance when no terms matched — how to verify the field name or adjust the count expression. Absent when terms are returned. |
| results | No | Term-count pairs sorted by count descending |
| termCount | No | Number of distinct terms returned |
| truncated | No | True when the term list was capped at the limit — more distinct terms may exist. |
| truncationCeiling | No | Count of the lowest-ranked term returned — omitted terms fall at or below it. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the description need not repeat safety. It adds valuable behavioral detail: sorting order, counting semantics ('append .exact'), and special handling for identifier fields (bare counting required). It also notes validation rejections (e.g., unbalanced quotes, backslash endings), which are useful edge cases. A small gap is not describing pagination or rate limits, but for a read-only aggregate tool the coverage is strong.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is information-dense and front-loaded with the core action and output. It earns each sentence, but it is slightly long and the final pairing sentence could be seen as extra. Still, it is well-organized and not padded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With a rich schema (100% parameter coverage), a clear output schema, and readOnlyHint annotation, the description fills the gaps that matter: interpretation of results (ranking), use with sibling tools, and critical .exact behavior. An agent has enough to invoke correctly without surprise.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, yet the description elevates parameter meaning significantly. It explains when to use .exact, warns that certain fields reject .exact, gives a concrete search example, and clarifies the default/max limit. This goes well beyond the schema's bare descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description states a specific verb ('Aggregate and tally'), a resource ('unique values for any field across any openFDA endpoint'), and the output format ('ranked term-count pairs sorted by count descending'). It clearly differentiates from sibling search tools by emphasizing aggregation over retrieval of records.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly names six sibling tools as complementary partners for interpreting aggregates ('Pair with...'). It does not spell out when NOT to use this tool, but the pairing guidance strongly implies this tool is for aggregation and those others are for sample records, which is clear directional guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openfda_dataframe_describeOpenfda Dataframe DescribeARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| canvas_id | Yes | Canvas ID from an openFDA search tool response (present when the search ran with stage=true). |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Present when the call failed. Absent on success. |
| tables | No | All tables and views available on this canvas. |
| canvas_id | No | Canvas ID that was described — pass to openfda_dataframe_query. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true. The description adds value beyond these by explaining row_count's full-scope meaning and warning that JSON columns hold nested objects needing DuckDB json functions. These are behavioral details not covered by annotations or schema, significantly aiding correct usage.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with zero redundancy. The core purpose and usage timing are front-loaded, followed by two essential caveats. Every sentence earns its place, making the description both compact and information-dense.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present (so return values need no explanation) and annotations covering read-only/idempotent behavior, the description supplies the remaining critical context: call order, row_count semantics, and JSON column handling. Nothing essential is missing for an agent to invoke this tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema fully describes canvas_id (coverage 100%), including its source and the stage=true condition. The description adds no new parameter-specific meaning beyond reinforcing that the canvas comes from an openFDA search tool, which the schema already states. Per the baseline for high coverage, a 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb ('list') and specific resource ('tables and column schemas on a DataCanvas staged by an openFDA search tool'). It differentiates itself from siblings by positioning as a discovery step for the subsequent query tool, making its purpose unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly instructs to 'Call before openfda_dataframe_query' to discover exact names and types, giving direct when-to-use guidance. It also clarifies row_count semantics ('full staged result set, not inline preview count'), preventing a common misuse. This fully addresses usage context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openfda_dataframe_queryOpenfda Dataframe QueryARead-onlyIdempotentInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| query | Yes | SQL SELECT against the staged table. Use the table name from openfda_dataframe_describe. Example: "SELECT classification, COUNT(*) AS n FROM spilled_ab12cd34 GROUP BY classification ORDER BY n DESC". | |
| canvas_id | Yes | Canvas ID from an openFDA search tool response (the canvas_id field, present when the search ran with stage=true). |
Output Schema
| Name | Required | Description |
|---|---|---|
| rows | No | Rows returned by the query (capped at the canvas row limit). |
| error | No | Present when the call failed. Absent on success. |
| canvas_id | No | Canvas ID that was queried — reuse for follow-up queries. |
| row_count | No | Number of rows in this response. Equals the canvas row limit when truncated is true. |
| truncated | No | True when the result hit the canvas row limit and rows beyond it were dropped. Page the rest with ORDER BY plus LIMIT/OFFSET. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true, and the description is consistent with and enriches them. It discloses the security boundary ('DDL, DML, COPY, and file-reading functions are blocked'), the row-cap behavior with the truncated flag, and crucially the storage semantics ('Scalar fields are stored as text (CAST for numeric math); nested objects/arrays are JSON columns') with a concrete json_extract_string example. This is exactly the behavioral context annotations cannot express, and it contradicts nothing.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single dense paragraph that front-loads the core purpose before layering preconditions, limits, type semantics, and restrictions. Every sentence carries distinct information (sequencing, truncation paging, CAST, JSON functions, blocked statements) with no filler. Slightly long, but the density is justified for a tool with this much operational nuance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
An output schema exists, so return-value documentation isn't the description's burden. Given the tool's complexity, it covers the essential operational surface: how to reach the right table, how to handle truncation, how to deal with column typing, and the safety boundary. It omits nothing needed to make a correct first call; a worked end-to-end query paired with the describe output is the only optional addition.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% — both canvas_id and query carry full descriptions with a worked SQL example. The description adds marginal value (the table name comes from openfda_dataframe_describe; canvas_id derives from a stage=true search), which aligns with the schema but does not materially extend it. Baseline 3 is appropriate when the schema already documents both parameters thoroughly.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb and resource: 'Run a read-only SQL SELECT against a DataCanvas table staged by an openFDA search tool'. It clearly distinguishes itself from sibling search tools by explaining it operates on already-staged results rather than paging the API, and it names its companion openfda_dataframe_describe. An agent can tell exactly what this tool does and how it relates to the other openfda_* siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicit sequencing is given: call a search tool with stage=true to obtain canvas_id/canvas_table, and 'Call openfda_dataframe_describe first to get the exact table and column names'. Truncation handling is prescribed ('page the rest with ORDER BY plus LIMIT/OFFSET'). It does not enumerate which sibling tools NOT to use (e.g., openfda_count_values for simple aggregations), so it stops just short of fully routing alternatives, but the preconditions are clear and actionable.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openfda_describe_fieldsOpenfda Describe FieldsARead-onlyInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| endpoint | Yes | openFDA endpoint to describe (e.g. "drug/event", "drug/shortages", "device/510k"). Must be one of the cataloged endpoints. |
Output Schema
| Name | Required | Description |
|---|---|---|
| error | No | Present when the call failed. Absent on success. |
| groups | No | Field groups for this endpoint |
| endpoint | No | The endpoint these fields apply to |
| queryTips | No | openFDA query syntax reminders relevant to this endpoint |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The readOnlyHint annotation already signals this is a safe read operation. The description adds behavioral context beyond that: it returns grouped categories with type and description, and emphasizes that field paths differ across endpoints. This is useful but does not describe the exact output structure; however, an output schema exists, so the return format is already documented. The description supplements annotations adequately.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler. The core purpose is front-loaded, followed immediately by the usage context and the rationale for why this tool exists. Every sentence earns its place, and the structure makes it easy for an agent to quickly grasp the tool's role.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple one-parameter discovery tool with an output schema already present, the description is fully complete. It explains what the tool does, when to use it, and why it's necessary, leaving no missing information that an agent would need to make a correct call. The presence of the output schema covers return values, so no further explanation is required.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema provides 100% coverage for the single 'endpoint' parameter, including an enum of valid values and a description. The tool description adds a rationale for why the endpoint parameter is needed (to identify the correct field paths), but does not provide additional syntax or format details beyond the schema. Given full schema coverage, the baseline score of 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Return the searchable field paths for an openFDA endpoint, grouped by category with type and description.' It identifies a specific verb (return), resource (field paths), and the grouping/type/description outcome. This distinguishes it from sibling search/count tools, which operate on data rather than metadata.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit when-to-use guidance: 'Use before constructing a search query to find the correct dotted field path.' It also explains why (field paths differ per endpoint and are not discoverable from the schema). It does not explicitly name an alternative tool, but the context of 'before constructing a search query' implies the correct timing and alternative search tools. This is clear usage guidance but lacks an explicit exclusion statement.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openfda_drug_profileOpenfda Drug ProfileARead-onlyInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| drug | Yes | Drug name to profile — brand or generic (e.g. "metformin", "Humira", "Glucophage"). Resolved once to canonical FDA identifiers, which then key every sub-query. |
Output Schema
| Name | Required | Description |
|---|---|---|
| meta | No | Request metadata. |
| error | No | Present when the call failed. Absent on success. |
| label | No | Label highlights from drug/label, or null when no label matched. |
| notice | No | Guidance when the drug could not be resolved or upstream errors degraded the profile. Absent on a fully populated profile. |
| recalls | No | Recent drug/enforcement recall actions (may be empty). |
| approval | No | Drugs@FDA approval summary, or null when no application matched. |
| degraded | No | Sub-queries that failed upstream, empty when every section resolved. A section listed here is unknown, not absent — a null section with no entry here genuinely has no FDA record. |
| identity | No | Identity resolved once and reused across every sub-query to avoid identifier drift. |
| shortage | No | Current or most-recent drug shortage status, or null when none on record. |
| sectionsFound | No | How many profile sections (label, adverse_events, recalls, approval, shortage) returned data. |
| adverse_events | No | Adverse-event summary aggregated over drug/event, or null when unavailable. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotation already declares readOnlyHint=true, so the safety profile is known. The description adds valuable behavioral context beyond that: fan-out in parallel, merging, best-effort sections that return null on misses, and reconciliation of identifier drift between endpoints. This goes well beyond the annotation, though it does not discuss rate limits or failure modes per sub-query, so not a 5.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences, each earning its place: the core action, the alternatives it replaces, the best-effort note, and routing guidance. The most important content (what it does) is front-loaded. No fluff or repetition of schema or annotation details.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a complex tool that subsumes five siblings, the description covers purpose, selection criteria, alternative routing, and behavioral expectations. It respects that an output schema exists to document return structure. Nothing an agent needs to decide whether to call it and what to expect is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the parameter's description already explains accepted values (brand or generic) and the resolution behavior. The tool description does not add extra parameter syntax or format details, but the schema carries the load. Baseline 3 is appropriate; there is no gap to penalize or extra value to reward.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Resolve... then fan out... and merge') and resource (drug profile), and enumerates the concrete sections (identity, label highlights, adverse-event summary, recall history, approval, shortage). It explicitly names the sibling tools it replaces, making it distinct from openfda_get_drug_label, openfda_search_adverse_events, etc. without needing to inspect their schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It says explicitly when to use this tool (for a combined profile) and when not ('For deep dives into any one area, use the dedicated tool'), and names the exact alternatives. It also flags the rationale (identifier drift) and the best-effort behavior, leaving no ambiguity about selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openfda_get_drug_labelOpenfda Get Drug LabelARead-onlyInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| skip | No | Number of records to skip for pagination (default 0). openFDA caps pagination at 25000 records; a higher value returns a pagination_limit_reached error. | |
| sort | No | Sort expression — a field path optionally suffixed with :asc or :desc; comma-separate for multi-field sort. Example: effective_time:desc. Field paths take only letters, digits, underscores, and dots; anything else is rejected before the request. A well-formed but non-sortable field still causes a query error — use a documented field name. | |
| limit | No | Maximum number of results to return (1-1000). Default 5. Labels are large, and the cost of a sections selection is the section summed across every record on the page — so it scales with this limit. Lower it before widening a selection. | |
| search | Yes | Query targeting label fields. Examples: openfda.brand_name:"aspirin", openfda.generic_name:"metformin", openfda.manufacturer_name:"pfizer". For a specific revision, pass set_id with the SPL UUID returned in earlier results. Double quotes, parentheses, and range brackets must balance, and the query must not end on a backslash — each is rejected before the request. | |
| sections | No | Label sections to return, e.g. ["boxed_warning","indications_and_usage"]. Names come from the outline an oversized page returns, or from openfda_describe_fields. Omit for the whole label — which returns the section outline instead when the page exceeds the inline size budget. A selection is returned whole even when it exceeds that budget, with its serialized size reported on the notice; the outline names a section measured to fit at the requested limit. Metadata (openfda, set_id, id, effective_time, version) is returned either way and counts toward the size. |
Output Schema
| Name | Required | Description |
|---|---|---|
| cap | No | The limit applied to this page. |
| kind | No | Whether this response carries label records ("full") or only the section outline of a page too large to inline ("outline"). |
| meta | No | Pagination and freshness metadata. |
| error | No | Present when the call failed. Absent on success. |
| shown | No | Number of labels returned in this response. |
| notice | No | Guidance for this page: how to broaden filters or correct field names when results are empty or paging overshot, the sized re-call example when a page overflowed to its section outline, section names no record carried, and the serialized size when a sections selection exceeds the inline budget. Absent when nothing needs saying. |
| outline | No | Section names available across the matched page and their serialized size, largest first. Present when kind is "outline" — pass names back in sections to retrieve them. |
| results | No | Drug label records, present when kind is "full". Each carries an openfda block (brand_name, generic_name, manufacturer_name, route) plus optional SPL sections like indications_and_usage, warnings, dosage_and_administration, contraindications, adverse_reactions; section presence varies per label. Narrowed to the requested sections plus metadata when sections was supplied. |
| truncated | No | True when more labels matched than this page returned — page with skip for the rest. |
| totalResults | No | Total matching label records in the dataset |
| effectiveQuery | No | Search filter applied to the drug label query, as submitted to openFDA |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The readOnlyHint annotation already covers the read-only nature, so the description appropriately focuses on extra behavioral details: the token-size budget, the fallback to a section outline, and the need to re-call with specific sections. This adds genuine value beyond the annotation and does not contradict it.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is compact and front-loaded with the primary purpose, then explains the important behavioral nuance in a single follow-up sentence. There is no filler or redundancy; every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 5 parameters and an output schema, the description covers the critical behavioral aspect—how large pages are handled and the sections mechanism—and mentions metadata inclusion indirectly via 'any structured label section.' The schema fills in parameter details, so the description is sufficient for an agent to understand what to expect, though it could briefly note the response structure beyond what the schema provides.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and each parameter has a detailed description (e.g., search examples, sort pattern, limit scaling). The description adds only a minor hint about the 'sections' parameter through the re-call guidance, but nothing that substantially enhances understanding beyond the schema. Baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool's purpose: 'Look up FDA drug labeling' with specific examples of label sections (indications, warnings, dosage, etc.). It is immediately distinct from sibling tools that search for adverse events, recalls, or approvals, and the verb 'look up' matches the read-only intent.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies when to use it (any time label content is needed) and provides a clear usage pattern for oversized pages: 're-call with sections to pull the ones you need.' It does not explicitly name alternatives or exclusions, but the domain is well defined and the fallback behavior is explained, giving an agent enough context to decide when this tool applies.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openfda_lookup_ndcOpenfda Lookup NdcARead-onlyInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| skip | No | Number of records to skip for pagination (default 0). openFDA caps pagination at 25000 records; a higher value returns a pagination_limit_reached error. | |
| sort | No | Sort expression — a field path optionally suffixed with :asc or :desc; comma-separate for multi-field sort. Example: listing_expiration_date:desc. Field paths take only letters, digits, underscores, and dots; anything else is rejected before the request. A well-formed but non-sortable field still causes a query error — use a documented field name. | |
| limit | No | Maximum number of records to return (1-1000, default 10). Serialized record size varies by three orders of magnitude across openFDA endpoints, so the page is also bounded by a 24000-byte serialized budget: a page that would overrun it returns fewer records than requested and reports the cut on page_omitted. Whenever any record matched, at least one comes back, however large it measures. A record grows with its packaging list, so a product with many package configurations is several times the size of one with a single package. | |
| stage | No | Stage the matched set on a DataCanvas for SQL analysis with openfda_dataframe_query. Default false — the call returns one page for one upstream request. When true, records are also drained onto a canvas table up to a size budget (staged_rows reports how many reached it). Staging is for record-level SQL over a bounded slice; for a distribution over everything that matched, openfda_count_values aggregates server-side in one request. Requires CANVAS_PROVIDER_TYPE=duckdb. | |
| search | Yes | openFDA search query. Examples: product_ndc:"0363-0218", brand_name:"aspirin", generic_name:"metformin", openfda.manufacturer_name:"walgreen", active_ingredients.name:"ASPIRIN". Double quotes, parentheses, and range brackets must balance, and the query must not end on a backslash — each is rejected before the request. | |
| canvas_id | No | DataCanvas session id from a prior call. Passing one stages this lookup onto that canvas (same effect as stage=true) so result sets accumulate for cross-table joins. Omit to stage onto a fresh canvas. |
Output Schema
| Name | Required | Description |
|---|---|---|
| meta | No | Response metadata |
| error | No | Present when the call failed. Absent on success. |
| notice | No | Canvas staging disclosure when the call staged, the byte-budget disclosure and the routes to the withheld records when the inline page was bounded, and guidance when results are empty — how to broaden filters or correct field names. |
| results | No | NDC directory records — product_ndc, brand_name, generic_name, labeler_name, dosage_form, route, marketing_category, active_ingredients[], packaging[], listing_expiration_date. |
| spilled | No | True when this call staged its matched set on the canvas — use canvas_id with openfda_dataframe_query for SQL. Absent when staging was not requested. |
| canvas_id | No | DataCanvas session id for the staged result set. Present when this call staged. Pass to openfda_dataframe_query / openfda_dataframe_describe, or back into this tool to accumulate more tables on the same canvas. |
| truncated | No | True when fewer rows reached the canvas than matched upstream — staging stopped at its size budget or openFDA's 25000-row pagination ceiling. Narrow the query (filters, date range) for a complete set. |
| page_bytes | No | Serialized size of results in this response, in bytes. Present only when the 24000-byte inline budget bounded the page; larger than the budget only when a single record exceeds it on its own. |
| staged_rows | No | Rows written to the canvas table. Compare with meta.total: a smaller value means staging stopped at its size budget and the table holds only the first staged_rows records. |
| canvas_table | No | Canvas table holding the staged rows. Present when rows were staged; reference it in SQL FROM clauses. |
| page_omitted | No | Records dropped from the requested limit/skip window so the page fit the inline byte budget. Present only when the page was bounded. Read them by re-calling with skip advanced by the number of records returned, lower limit for a smaller page, or pass stage=true to query a bounded drain of the match with openfda_dataframe_query. |
| totalResults | No | Total matching NDC records in the dataset |
| effectiveQuery | No | Search filter applied to the NDC lookup, as submitted to openFDA |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the safety profile is covered. The description adds a useful integration hint (pairing with get_drug_label) and mentions output fields, but does not disclose additional behavioral traits beyond what annotations and the schema (pagination, limits) already describe. A 3 is the appropriate baseline.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences with no wasted words: first states the core purpose, second lists searchable attributes, third gives a practical integration hint. The key 'look up drugs in NDC Directory' is front-loaded, making it instantly scannable.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the rich schema (all parameters documented) and an output schema, the description provides all necessary high-level context, including a pointer to a related tool for further steps. Pagination, sort, and other details are covered schematically, so nothing essential is omitted.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and all six parameters have detailed descriptions. The description adds no extra parameter-level meaning; only mentions output fields (brand_name, set_id) which is fine. Baseline 3 applies because the schema does the heavy lifting.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool looks up drugs in the NDC Directory and enumerates the specific identifiers it can find (NDC code, active ingredients, packaging, manufacturer). This differentiates it from siblings like openfda_search_adverse_events or openfda_get_drug_label without needing to inspect schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides a concrete use case (identify drug products) and explicitly suggests pairing with openfda_get_drug_label using returned fields, which is actionable. However, it does not explicitly mention when not to use this tool or contrast with similar options like openfda_drug_profile, so it misses the full 'when-not/alternatives' guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openfda_search_adverse_eventsOpenfda Search Adverse EventsARead-onlyInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| skip | No | Number of records to skip for pagination (default 0). openFDA caps pagination at 25000 records; a higher value returns a pagination_limit_reached error. | |
| sort | No | Sort expression — a field path optionally suffixed with :asc or :desc; comma-separate for multi-field sort. Field paths take only letters, digits, underscores, and dots; anything else is rejected before the request. Sortable date fields are category-specific: drug → receivedate:desc (or receiptdate), food → date_created:desc (or date_started), device → date_received:desc (or date_of_event). A field from another category (e.g. receivedate on food or device) causes a query error — use the field for this category. | |
| limit | No | Maximum number of records to return (1-1000, default 10). Serialized record size varies by three orders of magnitude across openFDA endpoints, so the page is also bounded by a 24000-byte serialized budget: a page that would overrun it returns fewer records than requested and reports the cut on page_omitted. Whenever any record matched, at least one comes back, however large it measures. Drug reports are by far the largest — a single drug/event report averages tens of kilobytes where a food/event report is a few hundred bytes. | |
| stage | No | Stage the matched set on a DataCanvas for SQL analysis with openfda_dataframe_query. Default false — the call returns one page for one upstream request. When true, records are also drained onto a canvas table up to a size budget (staged_rows reports how many reached it). Staging is for record-level SQL over a bounded slice; for a distribution over everything that matched, openfda_count_values aggregates server-side in one request. Requires CANVAS_PROVIDER_TYPE=duckdb. | |
| search | No | openFDA search query. Examples: patient.drug.medicinalproduct:"aspirin", patient.reaction.reactionmeddrapt:"nausea" AND serious:"1". Omit to browse recent. Double quotes, parentheses, and range brackets must balance, and the query must not end on a backslash — each is rejected before the request. | |
| category | Yes | Product category — each has different field schemas in the response | |
| canvas_id | No | DataCanvas session id from a prior call. Passing one stages this search onto that canvas (same effect as stage=true) so result sets accumulate for cross-table joins. Omit to stage onto a fresh canvas. |
Output Schema
| Name | Required | Description |
|---|---|---|
| meta | No | Response metadata |
| error | No | Present when the call failed. Absent on success. |
| notice | No | Canvas staging disclosure when the call staged, the byte-budget disclosure and the routes to the withheld records when the inline page was bounded, and guidance when results are empty or paging overshot — how to broaden filters or adjust the query. |
| results | No | Adverse event records — fields vary by category (drug: patient/reactions/drugs, device: device details/event type, food: products/outcomes) |
| spilled | No | True when this call staged its matched set on the canvas — use canvas_id with openfda_dataframe_query for SQL. Absent when staging was not requested. |
| canvas_id | No | DataCanvas session id for the staged result set. Present when this call staged. Pass to openfda_dataframe_query / openfda_dataframe_describe, or back into this tool to accumulate more tables on the same canvas. |
| truncated | No | True when fewer rows reached the canvas than matched upstream — staging stopped at its size budget or openFDA's 25000-row pagination ceiling. Narrow the query (filters, date range) for a complete set. |
| page_bytes | No | Serialized size of results in this response, in bytes. Present only when the 24000-byte inline budget bounded the page; larger than the budget only when a single record exceeds it on its own. |
| staged_rows | No | Rows written to the canvas table. Compare with meta.total: a smaller value means staging stopped at its size budget and the table holds only the first staged_rows records. |
| canvas_table | No | Canvas table holding the staged rows. Present when rows were staged; reference it in SQL FROM clauses. |
| page_omitted | No | Records dropped from the requested limit/skip window so the page fit the inline byte budget. Present only when the page was bounded. Read them by re-calling with skip advanced by the number of records returned, lower limit for a smaller page, or pass stage=true to query a bounded drain of the match with openfda_dataframe_query. |
| totalResults | No | Total matching adverse event records in the dataset |
| effectiveQuery | No | Search filter applied to the query, as submitted to openFDA |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the description does not need to state that this is a read operation. The description adds no behavioral detail beyond purpose; however, the input schema carries extensive behavioral notes (pagination limits, category-specific sort fields, staging behavior, byte budgets). Since annotations reduce the burden and the schema covers operational caveats, a score of 3 is appropriate rather than lower.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences with no filler: the first clearly states the verb and resource, the second enumerates three concrete use cases. Every word earns its place, and the core purpose is front-loaded.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 7 parameters and a rich output schema, the description gives enough context for an agent to understand what the tool does and when to use it. It does not reference the operational complexities (pagination limits, category-specific sorting, staging), but those are fully documented in the schema. The description is complete for decision-making, though not exhaustive.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the schema provides thorough explanations for every parameter (skip pagination cap, sort field limitations, limit byte budget, search syntax constraints, category enum, staging semantics). The description itself adds no parameter-level meaning beyond what the schema already provides, matching the baseline for high coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Search') and a precise resource ('adverse event reports across drugs, food, and devices'), and gives concrete use cases (investigate safety signals, find reports for a product, explore demographics). This clearly distinguishes it from sibling search tools for recalls, approvals, and animal events, even though no sibling is named.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit use cases ('investigate safety signals, find reports for a specific product, or explore reactions by demographics'), which implicitly tells the agent when to reach for this tool. It does not name alternatives or state exclusions, but given the domain-specific nature of the tool and the sibling set, the context is sufficient to guide selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openfda_search_animal_eventsOpenfda Search Animal EventsARead-onlyInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| skip | No | Number of records to skip for pagination (default 0). openFDA caps pagination at 25000 records; a higher value returns a pagination_limit_reached error. | |
| sort | No | Sort expression — a field path optionally suffixed with :asc or :desc; comma-separate for multi-field sort. Example: original_receive_date:desc. Field paths take only letters, digits, underscores, and dots; anything else is rejected before the request. A well-formed but non-sortable field still causes a query error — use a documented field name. | |
| limit | No | Maximum number of records to return (1-1000, default 10). Serialized record size varies by three orders of magnitude across openFDA endpoints, so the page is also bounded by a 24000-byte serialized budget: a page that would overrun it returns fewer records than requested and reports the cut on page_omitted. Whenever any record matched, at least one comes back, however large it measures. | |
| stage | No | Stage the matched set on a DataCanvas for SQL analysis with openfda_dataframe_query. Default false — the call returns one page for one upstream request. When true, records are also drained onto a canvas table up to a size budget (staged_rows reports how many reached it). Staging is for record-level SQL over a bounded slice; for a distribution over everything that matched, openfda_count_values aggregates server-side in one request. Requires CANVAS_PROVIDER_TYPE=duckdb. | |
| search | No | openFDA search query using field:value syntax. Examples: animal.species:"Dog", drug.brand_name:"Bravecto", reaction.veddra_term_name:"Vomiting", serious_ae:"true". Omit to browse recent reports. Double quotes, parentheses, and range brackets must balance, and the query must not end on a backslash — each is rejected before the request. | |
| canvas_id | No | DataCanvas session id from a prior call. Passing one stages this search onto that canvas (same effect as stage=true) so result sets accumulate for cross-table joins. Omit to stage onto a fresh canvas. |
Output Schema
| Name | Required | Description |
|---|---|---|
| meta | No | Response metadata |
| error | No | Present when the call failed. Absent on success. |
| notice | No | Canvas staging disclosure when the call staged, the byte-budget disclosure and the routes to the withheld records when the inline page was bounded, and guidance when results are empty or paging overshot — how to broaden filters or adjust the query. |
| results | No | Animal adverse event records. Key fields: unique_aer_id_number, original_receive_date, serious_ae, animal (species, gender, breed, age, weight), drug[] (brand_name, active_ingredients, route, dose, administered_by), reaction[] (veddra_term_name, number_of_animals_affected), outcome[] (medical_status), primary_reporter, type_of_information. |
| spilled | No | True when this call staged its matched set on the canvas — use canvas_id with openfda_dataframe_query for SQL. Absent when staging was not requested. |
| canvas_id | No | DataCanvas session id for the staged result set. Present when this call staged. Pass to openfda_dataframe_query / openfda_dataframe_describe, or back into this tool to accumulate more tables on the same canvas. |
| truncated | No | True when fewer rows reached the canvas than matched upstream — staging stopped at its size budget or openFDA's 25000-row pagination ceiling. Narrow the query (filters, date range) for a complete set. |
| page_bytes | No | Serialized size of results in this response, in bytes. Present only when the 24000-byte inline budget bounded the page; larger than the budget only when a single record exceeds it on its own. |
| staged_rows | No | Rows written to the canvas table. Compare with meta.total: a smaller value means staging stopped at its size budget and the table holds only the first staged_rows records. |
| canvas_table | No | Canvas table holding the staged rows. Present when rows were staged; reference it in SQL FROM clauses. |
| page_omitted | No | Records dropped from the requested limit/skip window so the page fit the inline byte budget. Present only when the page was bounded. Read them by re-calling with skip advanced by the number of records returned, lower limit for a smaller page, or pass stage=true to query a bounded drain of the match with openfda_dataframe_query. |
| totalResults | No | Total matching animal adverse event records in the dataset |
| effectiveQuery | No | Search filter applied to the query, as submitted to openFDA |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true, so the read-only nature is already covered. The description adds context about the data fields (species, breed, age, reactions, outcome) but does not disclose pagination limits, staging behavior, or response format—these are handled in the schema. It neither contradicts annotations nor adds significant behavioral nuance beyond the safety hint, so baseline 3 is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no filler. The first sentence states purpose and data content, the second gives use cases. Everything earns its place and is front-loaded, making it easy for an agent to quickly grasp the tool's function.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the detailed input schema (100% coverage) and an output schema, the description is sufficiently complete for correct invocation. It covers domain, data elements, and typical use cases. It doesn't repeat schema details, which is appropriate, though it omits nuanced behaviors like staging or pagination limits that are already documented in the schema.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and each parameter has a detailed description covering syntax, defaults, and edge cases (e.g., pagination limit, serialized size budget, staging semantics). The tool description adds minimal parameter-specific meaning, only implying the searchable fields. Baseline 3 is suitable because the schema already carries the full semantic load.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb (search) and resource (adverse event reports for veterinary drugs and devices) and explicitly scopes to the FDA Center for Veterinary Medicine. It lists the record contents and distinguishes from the sibling openfda_search_adverse_events by specifying the veterinary focus, so an agent can tell them apart without opening schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides clear usage context: 'investigate safety signals for veterinary products, find reports by animal species or drug, or explore reaction patterns.' It does not explicitly mention when not to use it or name alternative tools, but the purpose and data scope make the intended use obvious. Lacks explicit exclusions but gives appropriate situational guidance.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openfda_search_device_clearancesOpenfda Search Device ClearancesBRead-onlyInspect
Search FDA device premarket notifications — 510(k) clearances and PMA approvals.
| Name | Required | Description | Default |
|---|---|---|---|
| skip | No | Number of records to skip for pagination (default 0). openFDA caps pagination at 25000 records; a higher value returns a pagination_limit_reached error. | |
| sort | No | Sort expression — a field path optionally suffixed with :asc or :desc; comma-separate for multi-field sort. Example: decision_date:desc. Field paths take only letters, digits, underscores, and dots; anything else is rejected before the request. A well-formed but non-sortable field still causes a query error — use a documented field name. | |
| limit | No | Maximum number of records to return (1-1000, default 10). Serialized record size varies by three orders of magnitude across openFDA endpoints, so the page is also bounded by a 24000-byte serialized budget: a page that would overrun it returns fewer records than requested and reports the cut on page_omitted. Whenever any record matched, at least one comes back, however large it measures. A 510(k) record carries a summary narrative and is several times the size of a PMA record. | |
| stage | No | Stage the matched set on a DataCanvas for SQL analysis with openfda_dataframe_query. Default false — the call returns one page for one upstream request. When true, records are also drained onto a canvas table up to a size budget (staged_rows reports how many reached it). Staging is for record-level SQL over a bounded slice; for a distribution over everything that matched, openfda_count_values aggregates server-side in one request. Requires CANVAS_PROVIDER_TYPE=duckdb. | |
| search | No | openFDA search query. Examples: applicant:"medtronic", advisory_committee_description:"cardiovascular", product_code:"DXN", openfda.device_name:"catheter". Omit to browse recent. Double quotes, parentheses, and range brackets must balance, and the query must not end on a backslash — each is rejected before the request. | |
| pathway | Yes | Premarket pathway. 510(k) is the most common; PMA is for higher-risk devices. | |
| canvas_id | No | DataCanvas session id from a prior call. Passing one stages this search onto that canvas (same effect as stage=true) so result sets accumulate for cross-table joins. Omit to stage onto a fresh canvas. |
Output Schema
| Name | Required | Description |
|---|---|---|
| meta | No | Response metadata |
| error | No | Present when the call failed. Absent on success. |
| notice | No | Canvas staging disclosure when the call staged, the byte-budget disclosure and the routes to the withheld records when the inline page was bounded, and guidance when results are empty — how to broaden filters or correct field names. |
| results | No | 510(k) or PMA records — 510(k) carries k_number, device_name, applicant, product_code, decision_date, decision_description, advisory_committee_description; PMA carries pma_number, trade_name, generic_name, supplement_number plus shared applicant/product_code/decision_date/decision_description. |
| spilled | No | True when this call staged its matched set on the canvas — use canvas_id with openfda_dataframe_query for SQL. Absent when staging was not requested. |
| canvas_id | No | DataCanvas session id for the staged result set. Present when this call staged. Pass to openfda_dataframe_query / openfda_dataframe_describe, or back into this tool to accumulate more tables on the same canvas. |
| truncated | No | True when fewer rows reached the canvas than matched upstream — staging stopped at its size budget or openFDA's 25000-row pagination ceiling. Narrow the query (filters, date range) for a complete set. |
| page_bytes | No | Serialized size of results in this response, in bytes. Present only when the 24000-byte inline budget bounded the page; larger than the budget only when a single record exceeds it on its own. |
| staged_rows | No | Rows written to the canvas table. Compare with meta.total: a smaller value means staging stopped at its size budget and the table holds only the first staged_rows records. |
| canvas_table | No | Canvas table holding the staged rows. Present when rows were staged; reference it in SQL FROM clauses. |
| page_omitted | No | Records dropped from the requested limit/skip window so the page fit the inline byte budget. Present only when the page was bounded. Read them by re-calling with skip advanced by the number of records returned, lower limit for a smaller page, or pass stage=true to query a bounded drain of the match with openfda_dataframe_query. |
| totalResults | No | Total matching device clearance records in the dataset |
| effectiveQuery | No | Search filter applied to the device clearance query, as submitted to openFDA |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, so the description need not repeat that. The description adds no additional behavioral context (e.g., pagination limits, large-record implications, or error behavior). However, it does not contradict the annotation, and given the readOnlyHint coverage, a baseline score is appropriate.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single, front-loaded sentence that states exactly what the tool does with no filler. Every word earns its place; it is appropriately sized for a search tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 7-parameter tool with an output schema and rich schema descriptions, the description is minimal but the schema covers parameter semantics and the output schema covers return structure. The main gap is the lack of usage guidance and behavioral context (e.g., mention that 510(k) records are larger than PMA records, which the schema does note). Overall, the description is adequate but not complete on its own.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with all seven parameters documented in the schema (including detailed notes on each). The description itself contributes zero parameter-level meaning. Baseline 3 is fair because the schema fully carries the parameter semantics.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Search') and a resource ('FDA device premarket notifications') with explicit subtypes ('510(k) clearances and PMA approvals'). It clearly distinguishes from drug-related search tools like openfda_search_drug_approvals, but does not reference any sibling by name, so the differentiation is implicit rather than explicit.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives. It does not mention categories like 'use for device clearance documents' or contrast with drug-related searches. The sibling names exist (e.g., openfda_search_drug_approvals) but are not referenced, leaving selection entirely to the agent's inference from the resource name.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openfda_search_drug_approvalsOpenfda Search Drug ApprovalsARead-onlyInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| skip | No | Number of records to skip for pagination (default 0). openFDA caps pagination at 25000 records; a higher value returns a pagination_limit_reached error. | |
| sort | No | Sort expression — a field path optionally suffixed with :asc or :desc; comma-separate for multi-field sort. Example: submissions.submission_status_date:desc. Field paths take only letters, digits, underscores, and dots; anything else is rejected before the request. A well-formed but non-sortable field still causes a query error — use a documented field name. | |
| limit | No | Maximum number of records to return (1-1000, default 10). Serialized record size varies by three orders of magnitude across openFDA endpoints, so the page is also bounded by a 24000-byte serialized budget: a page that would overrun it returns fewer records than requested and reports the cut on page_omitted. Whenever any record matched, at least one comes back, however large it measures. A record carries its application's whole submission history, so a long-running application is an order of magnitude larger than a recent one. | |
| stage | No | Stage the matched set on a DataCanvas for SQL analysis with openfda_dataframe_query. Default false — the call returns one page for one upstream request. When true, records are also drained onto a canvas table up to a size budget (staged_rows reports how many reached it). Staging is for record-level SQL over a bounded slice; for a distribution over everything that matched, openfda_count_values aggregates server-side in one request. Requires CANVAS_PROVIDER_TYPE=duckdb. | |
| search | No | openFDA search query. Examples: openfda.brand_name:"humira", sponsor_name:"PFIZER", submissions.submission_type:"ORIG" AND submissions.review_priority:"PRIORITY". Exact quoted values can be case-sensitive on some fields — sponsor_name is stored uppercase, so use sponsor_name:"PFIZER" (a lowercase quoted value returns no matches). Omit to browse recent. Double quotes, parentheses, and range brackets must balance, and the query must not end on a backslash — each is rejected before the request. | |
| canvas_id | No | DataCanvas session id from a prior call. Passing one stages this search onto that canvas (same effect as stage=true) so result sets accumulate for cross-table joins. Omit to stage onto a fresh canvas. |
Output Schema
| Name | Required | Description |
|---|---|---|
| meta | No | Response metadata |
| error | No | Present when the call failed. Absent on success. |
| notice | No | Canvas staging disclosure when the call staged, the byte-budget disclosure and the routes to the withheld records when the inline page was bounded, and guidance when results are empty — how to broaden filters or correct field names. |
| results | No | Drug application records — application_number, sponsor_name, openfda block (brand_name, generic_name, route, product_type, substance_name), products[] (active_ingredients, dosage_form, marketing_status), submissions[] (submission_type, submission_status, submission_status_date, review_priority). |
| spilled | No | True when this call staged its matched set on the canvas — use canvas_id with openfda_dataframe_query for SQL. Absent when staging was not requested. |
| canvas_id | No | DataCanvas session id for the staged result set. Present when this call staged. Pass to openfda_dataframe_query / openfda_dataframe_describe, or back into this tool to accumulate more tables on the same canvas. |
| truncated | No | True when fewer rows reached the canvas than matched upstream — staging stopped at its size budget or openFDA's 25000-row pagination ceiling. Narrow the query (filters, date range) for a complete set. |
| page_bytes | No | Serialized size of results in this response, in bytes. Present only when the 24000-byte inline budget bounded the page; larger than the budget only when a single record exceeds it on its own. |
| staged_rows | No | Rows written to the canvas table. Compare with meta.total: a smaller value means staging stopped at its size budget and the table holds only the first staged_rows records. |
| canvas_table | No | Canvas table holding the staged rows. Present when rows were staged; reference it in SQL FROM clauses. |
| page_omitted | No | Records dropped from the requested limit/skip window so the page fit the inline byte budget. Present only when the page was bounded. Read them by re-calling with skip advanced by the number of records returned, lower limit for a smaller page, or pass stage=true to query a bounded drain of the match with openfda_dataframe_query. |
| totalResults | No | Total matching drug approval records in the dataset |
| effectiveQuery | No | Search filter applied to the Drugs@FDA query, as submitted to openFDA |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The annotation readOnlyHint=true already conveys the read-only nature, lowering the burden on the description. The description adds that it returns 'application details, sponsor info, and full submission history', which is marginally beyond the annotation but not deeply behavioral (e.g., pagination, errors are left to the schema). No contradictions with annotations found.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is exactly two sentences: the first front-loads the core purpose, and the second provides concise pairing guidance. Every phrase adds value; no redundancy or filler exists.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given an output schema exists and the parameter schema fully documents all 6 optional parameters, the description covers the essential usage context. It explains where the data comes from, what it returns, and how to extend the workflow with complementary tools. Nothing critical for an agent to call the tool correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema has 100% coverage with detailed descriptions for each of the 6 parameters, including pagination limits, sort syntax, staging behavior, and search examples. The description does not need to add parameter-level detail, so a baseline score of 3 is appropriate. It even hints at aggregatable fields (sponsor_name, product_type, route) which complements the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Search'), resource ('Drugs@FDA database'), and scope ('drug application approvals (NDAs and ANDAs)'), making the tool's purpose unambiguous. It also distinguishes from siblings like openfda_search_adverse_events by focusing on approvals, and mentions the return content (application details, sponsor info, submission history).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly recommends pairing with openfda_get_drug_label to read approved labels and openfda_count_values for aggregation, providing clear workflow guidance. It implies when to use this tool versus alternatives by naming the database and approval focus, though it does not explicitly exclude other search tools. The purpose is distinct enough that an agent can infer when to choose this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openfda_search_drug_shortagesOpenfda Search Drug ShortagesARead-onlyInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| skip | No | Number of records to skip for pagination (default 0). openFDA caps pagination at 25000 records; a higher value returns a pagination_limit_reached error. | |
| sort | No | Sort expression — a field path optionally suffixed with :asc or :desc; comma-separate for multi-field sort. Example: update_date:desc. Field paths take only letters, digits, underscores, and dots; anything else is rejected before the request. A well-formed but non-sortable field still causes a query error — use a documented field name. | |
| limit | No | Maximum number of records to return (1-1000, default 10). Serialized record size varies by three orders of magnitude across openFDA endpoints, so the page is also bounded by a 24000-byte serialized budget: a page that would overrun it returns fewer records than requested and reports the cut on page_omitted. Whenever any record matched, at least one comes back, however large it measures. | |
| stage | No | Stage the matched set on a DataCanvas for SQL analysis with openfda_dataframe_query. Default false — the call returns one page for one upstream request. When true, records are also drained onto a canvas table up to a size budget (staged_rows reports how many reached it). Staging is for record-level SQL over a bounded slice; for a distribution over everything that matched, openfda_count_values aggregates server-side in one request. Requires CANVAS_PROVIDER_TYPE=duckdb. | |
| search | No | openFDA search query using field:value syntax. Examples: status:"Current", therapeutic_category:"Oncology", generic_name:"carboplatin", company_name:"pfizer". Omit to browse all records. Double quotes, parentheses, and range brackets must balance, and the query must not end on a backslash — each is rejected before the request. Call openfda_describe_fields({ endpoint: "drug/shortages" }) for the complete field list. | |
| canvas_id | No | DataCanvas session id from a prior call. Passing one stages this search onto that canvas (same effect as stage=true) so result sets accumulate for cross-table joins. Omit to stage onto a fresh canvas. |
Output Schema
| Name | Required | Description |
|---|---|---|
| meta | No | Response metadata |
| error | No | Present when the call failed. Absent on success. |
| notice | No | Canvas staging disclosure when the call staged, the byte-budget disclosure and the routes to the withheld records when the inline page was bounded, and guidance when results are empty — how to broaden filters or correct field names. |
| results | No | Drug shortage records. Key fields: generic_name, status ("Current"/"Resolved"), availability, therapeutic_category, dosage_form, presentation, package_ndc, company_name, contact_info, initial_posting_date, update_date, update_type. openfda block contains brand_name, product_ndc, rxcui, spl_set_id for cross-linking. |
| spilled | No | True when this call staged its matched set on the canvas — use canvas_id with openfda_dataframe_query for SQL. Absent when staging was not requested. |
| canvas_id | No | DataCanvas session id for the staged result set. Present when this call staged. Pass to openfda_dataframe_query / openfda_dataframe_describe, or back into this tool to accumulate more tables on the same canvas. |
| truncated | No | True when fewer rows reached the canvas than matched upstream — staging stopped at its size budget or openFDA's 25000-row pagination ceiling. Narrow the query (filters, date range) for a complete set. |
| page_bytes | No | Serialized size of results in this response, in bytes. Present only when the 24000-byte inline budget bounded the page; larger than the budget only when a single record exceeds it on its own. |
| staged_rows | No | Rows written to the canvas table. Compare with meta.total: a smaller value means staging stopped at its size budget and the table holds only the first staged_rows records. |
| canvas_table | No | Canvas table holding the staged rows. Present when rows were staged; reference it in SQL FROM clauses. |
| page_omitted | No | Records dropped from the requested limit/skip window so the page fit the inline byte budget. Present only when the page was bounded. Read them by re-calling with skip advanced by the number of records returned, lower limit for a smaller page, or pass stage=true to query a bounded drain of the match with openfda_dataframe_query. |
| totalResults | No | Total matching drug shortage records in the dataset |
| effectiveQuery | No | Search filter applied to the drug/shortages query, as submitted to openFDA |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations carry readOnlyHint=true, lowering the safety burden. The description goes beyond this by disclosing exactly what is returned and the chaining behavior for the openfda block. Parameter descriptions add further behavioral context (pagination caps, staged_row cutoffs, sort rejection). No contradiction with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three front-loaded sentences with zero waste: purpose and returned fields first, then use cases, then chaining targets. Every sentence earns its place and the most decision-relevant info (what it does, what it returns) leads.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With an output schema present, return values need no explanation in the description. Zero required parameters, all 6 params fully documented in the schema, and the description covers purpose, use cases, and cross-tool chaining. Nothing an agent needs to call it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with detailed descriptions on all 6 parameters (pagination bounds, sort syntax, stage budget, search field examples, canvas_id semantics). Baseline 3 applies; the description itself adds no parameter details beyond what the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
States a specific verb+resource ("Search FDA drug shortage records") and enumerates the returned fields (status, availability, therapeutic category, dosage form, manufacturer, dates). It clearly differentiates from sibling search tools by scoping to the drug/shortages endpoint and names the two chaining targets (openfda_get_drug_label, openfda_lookup_ndc).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly lists concrete use cases: checking current shortage status, finding oncology drugs with supply issues, and retrieving the openfda block for chaining. The stage parameter additionally routes to openfda_count_values and openfda_dataframe_query as alternatives. It lacks an explicit when-NOT-to-use statement, but given the sibling set is all distinct endpoints, the guidance is sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openfda_search_recallsOpenfda Search RecallsCRead-onlyInspect
Search enforcement reports and recall actions across drugs, food, and devices.
| Name | Required | Description | Default |
|---|---|---|---|
| skip | No | Number of records to skip for pagination (default 0). openFDA caps pagination at 25000 records; a higher value returns a pagination_limit_reached error. | |
| sort | No | Sort expression — a field path optionally suffixed with :asc or :desc; comma-separate for multi-field sort (e.g. report_date:desc,status.exact:asc). Field paths take only letters, digits, underscores, and dots; anything else is rejected before the request. A well-formed but non-sortable field still causes a query error — use a documented field name. | |
| limit | No | Maximum number of records to return (1-1000, default 10). Serialized record size varies by three orders of magnitude across openFDA endpoints, so the page is also bounded by a 24000-byte serialized budget: a page that would overrun it returns fewer records than requested and reports the cut on page_omitted. Whenever any record matched, at least one comes back, however large it measures. Device records are the largest here — a device enforcement or recall record runs several kilobytes where a drug or food enforcement record is around one. | |
| stage | No | Stage the matched set on a DataCanvas for SQL analysis with openfda_dataframe_query. Default false — the call returns one page for one upstream request. When true, records are also drained onto a canvas table up to a size budget (staged_rows reports how many reached it). Staging is for record-level SQL over a bounded slice; for a distribution over everything that matched, openfda_count_values aggregates server-side in one request. Requires CANVAS_PROVIDER_TYPE=duckdb. | |
| search | No | openFDA search query. Examples: classification:"Class I" (also "Class II" or "Class III"), recalling_firm:"pfizer", reason_for_recall:"undeclared allergen". Omit to browse recent. Double quotes, parentheses, and range brackets must balance, and the query must not end on a backslash — each is rejected before the request. | |
| category | Yes | Product category | |
| endpoint | No | Report type. Default enforcement. The recall endpoint is only available for devices. | enforcement |
| canvas_id | No | DataCanvas session id from a prior call. Passing one stages this search onto that canvas (same effect as stage=true) so result sets accumulate for cross-table joins. Omit to stage onto a fresh canvas. |
Output Schema
| Name | Required | Description |
|---|---|---|
| meta | No | Response metadata |
| error | No | Present when the call failed. Absent on success. |
| notice | No | Canvas staging disclosure when the call staged, the byte-budget disclosure and the routes to the withheld records when the inline page was bounded, and guidance when results are empty — how to broaden filters or correct field names. |
| results | No | Enforcement or recall records — recall_number, classification, recalling_firm, product_description, reason_for_recall, status, voluntary_mandated, distribution_pattern, report_date. Field set varies between enforcement and recall endpoints. |
| spilled | No | True when this call staged its matched set on the canvas — use canvas_id with openfda_dataframe_query for SQL. Absent when staging was not requested. |
| canvas_id | No | DataCanvas session id for the staged result set. Present when this call staged. Pass to openfda_dataframe_query / openfda_dataframe_describe, or back into this tool to accumulate more tables on the same canvas. |
| truncated | No | True when fewer rows reached the canvas than matched upstream — staging stopped at its size budget or openFDA's 25000-row pagination ceiling. Narrow the query (filters, date range) for a complete set. |
| page_bytes | No | Serialized size of results in this response, in bytes. Present only when the 24000-byte inline budget bounded the page; larger than the budget only when a single record exceeds it on its own. |
| staged_rows | No | Rows written to the canvas table. Compare with meta.total: a smaller value means staging stopped at its size budget and the table holds only the first staged_rows records. |
| canvas_table | No | Canvas table holding the staged rows. Present when rows were staged; reference it in SQL FROM clauses. |
| page_omitted | No | Records dropped from the requested limit/skip window so the page fit the inline byte budget. Present only when the page was bounded. Read them by re-calling with skip advanced by the number of records returned, lower limit for a smaller page, or pass stage=true to query a bounded drain of the match with openfda_dataframe_query. |
| totalResults | No | Total matching recall/enforcement records in the dataset |
| effectiveQuery | No | Search filter applied to the recall query, as submitted to openFDA |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The only annotation is readOnlyHint=true, which is consistent with the 'Search' action, but the description adds no behavioral context beyond that. It does not mention pagination limits, result size budgets, staging behavior, or any other operational traits. The schema descriptions cover some behaviors (e.g., pagination cap, size budget), but the tool description itself is silent, so the agent must read the schema to learn these details.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, compact sentence that front-loads the purpose and includes the key categories. It is concise with no filler. However, it is so brief that it omits contextual guidance that would be useful for an 8-parameter tool, which slightly reduces its structural value despite its efficiency.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (8 parameters, two endpoints, three categories, an output schema), a single-sentence description is insufficient. It does not explain the difference between the 'enforcement' and 'recall' endpoints, when to use one over the other, or any high-level usage nuances. The schema carries this weight, but the description fails to summarize key decisions or point the agent to relevant alternatives, leaving the agent to dive into the schema without guidance.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool description contains no parameter information, but the schema provides 100% coverage with detailed descriptions for all 8 parameters, including defaults, constraints, examples, and behavioral notes (e.g., pagination cap, size budget for limit, staging behavior for stage/canvas_id). The description adds no meaning beyond what the schema already provides, so it meets the baseline for high schema coverage.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a clear verb ('Search') and a specific resource ('enforcement reports and recall actions') across three categories (drugs, food, devices). It is unambiguous about the subject matter, though it does not explicitly differentiate from sibling search tools like openfda_search_adverse_events or openfda_search_device_clearances. The name itself is specific enough that an agent can infer its scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides no guidance on when to use this tool versus alternatives. It does not mention exclusions, alternative tools, or any decision criteria. The parameter schema includes a note about staging vs. openfda_count_values, but that is buried in parameter descriptions and not surfaced in the tool description itself. An agent cannot tell from the description when to choose this over another search tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
openfda_search_tobacco_reportsOpenfda Search Tobacco ReportsARead-onlyInspect
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.
| Name | Required | Description | Default |
|---|---|---|---|
| skip | No | Number of records to skip for pagination (default 0). openFDA caps pagination at 25000 records; a higher value returns a pagination_limit_reached error. | |
| sort | No | Sort expression — a field path optionally suffixed with :asc or :desc; comma-separate for multi-field sort. Example: date_submitted:desc. Field paths take only letters, digits, underscores, and dots; anything else is rejected before the request. A well-formed but non-sortable field still causes a query error — use a documented field name. | |
| limit | No | Maximum number of records to return (1-1000, default 10). Serialized record size varies by three orders of magnitude across openFDA endpoints, so the page is also bounded by a 24000-byte serialized budget: a page that would overrun it returns fewer records than requested and reports the cut on page_omitted. Whenever any record matched, at least one comes back, however large it measures. | |
| stage | No | Stage the matched set on a DataCanvas for SQL analysis with openfda_dataframe_query. Default false — the call returns one page for one upstream request. When true, records are also drained onto a canvas table up to a size budget (staged_rows reports how many reached it). Staging is for record-level SQL over a bounded slice; for a distribution over everything that matched, openfda_count_values aggregates server-side in one request. Requires CANVAS_PROVIDER_TYPE=duckdb. | |
| search | No | openFDA search query using field:value syntax. Examples: tobacco_products:"Electronic cigarette", reported_health_problems:"Seizure", nonuser_affected:"Yes". Omit to browse recent reports. Double quotes, parentheses, and range brackets must balance, and the query must not end on a backslash — each is rejected before the request. | |
| canvas_id | No | DataCanvas session id from a prior call. Passing one stages this search onto that canvas (same effect as stage=true) so result sets accumulate for cross-table joins. Omit to stage onto a fresh canvas. |
Output Schema
| Name | Required | Description |
|---|---|---|
| meta | No | Response metadata |
| error | No | Present when the call failed. Absent on success. |
| notice | No | Canvas staging disclosure when the call staged, the byte-budget disclosure and the routes to the withheld records when the inline page was bounded, and guidance when results are empty or paging overshot — how to broaden filters or adjust the query. |
| results | No | Tobacco problem report records. Key fields: report_id, date_submitted, tobacco_products[] (product type description), reported_health_problems[] (health effects), reported_product_problems[] (device/product defects), number_tobacco_products, number_health_problems, number_product_problems, nonuser_affected. |
| spilled | No | True when this call staged its matched set on the canvas — use canvas_id with openfda_dataframe_query for SQL. Absent when staging was not requested. |
| canvas_id | No | DataCanvas session id for the staged result set. Present when this call staged. Pass to openfda_dataframe_query / openfda_dataframe_describe, or back into this tool to accumulate more tables on the same canvas. |
| truncated | No | True when fewer rows reached the canvas than matched upstream — staging stopped at its size budget or openFDA's 25000-row pagination ceiling. Narrow the query (filters, date range) for a complete set. |
| page_bytes | No | Serialized size of results in this response, in bytes. Present only when the 24000-byte inline budget bounded the page; larger than the budget only when a single record exceeds it on its own. |
| staged_rows | No | Rows written to the canvas table. Compare with meta.total: a smaller value means staging stopped at its size budget and the table holds only the first staged_rows records. |
| canvas_table | No | Canvas table holding the staged rows. Present when rows were staged; reference it in SQL FROM clauses. |
| page_omitted | No | Records dropped from the requested limit/skip window so the page fit the inline byte budget. Present only when the page was bounded. Read them by re-calling with skip advanced by the number of records returned, lower limit for a smaller page, or pass stage=true to query a bounded drain of the match with openfda_dataframe_query. |
| totalResults | No | Total matching tobacco problem reports in the dataset |
| effectiveQuery | No | Search filter applied to the query, as submitted to openFDA |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, and the description does not contradict that. The description adds minimal behavioral context beyond what annotations provide – it mentions the types of data captured but does not disclose pagination limits, error behaviors, or any side effects. Since annotations cover the safety profile, the description's extra information is useful but not extensive.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single, reasonably concise paragraph of three sentences that front-loads the core purpose and follows with examples of report content and use cases. It contains no filler or repetition, though it could be slightly tightened by moving some detail into the schema, but it remains efficient and well-structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is complete enough for an agent to select and call the tool: it covers what the tool does, what data it returns, and common use cases. Output schema is present, so return details are covered there. It does not explicitly mention error conditions or rate limits, but those are documented in parameter descriptions. For a search tool with no required parameters and clear annotations, the contextual information is sufficient.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, with all six parameters (skip, sort, limit, stage, search, canvas_id) having detailed descriptions including examples and constraints. The tool description repeats some example search fields (e.g., reported_health_problems) that also appear in the schema, adding minimal new meaning. It does not compensate for any parameter gaps because there are none, so a baseline 3 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Search') and resource ('problem reports submitted to the FDA for tobacco products'), and enumerates the content of those reports (product type, health problems, product problems, etc.). It clearly differentiates from sibling search tools like openfda_search_adverse_events by explicitly scoping to tobacco products, making it unambiguous what this tool is for.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear use cases ('investigate safety signals, find reports by product type, or analyze health effects') that indicate when the tool is appropriate. It does not explicitly name alternatives or state when not to use it, but the domain-specific language implicitly distinguishes it from other product-type search tools. This is clear context without explicit exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Frequently Asked Questions
Claiming proves that you control a remote MCP connector. It does not move, proxy, or interrupt the server.
Open the connector listing, choose Claim ownership, and sign in to Glama.
Complete one verification method:
GitHub identity — fastest for official registry listings. For a namespace such as
io.github.alice/server, link the matching GitHub user or an account that owns the GitHub organization, then choose Claim with GitHub.HTTP challenge — works when you can deploy a public file. Generate a token, publish the exact JSON Glama shows at
/.well-known/glama.jsonon the same origin as the connector, then choose Check HTTP challenge.DNS challenge — works when you control DNS but cannot change the server. Generate a token, create the exact TXT record Glama shows, wait for it to propagate, then choose Check DNS challenge.
After verification, Glama sends a confirmation email and gives you access to listing details, thumbnails, health checks, and analytics. Keep the HTTP file or DNS record in place: Glama periodically checks it and ownership remains verified while the token is discoverable.
The HTTP ownership file has this structure:
{
"$schema": "https://glama.ai/mcp/schemas/connector.json",
"claim": "glama_claim_..."
}Claim tokens are opaque, stable, and bound to the signed-in Glama account. They contain no email address or other personal information. If Glama can no longer discover a verified HTTP or DNS token, it starts a seven-day grace period before removing claim-based access. Restore the same token during that period to keep ownership verified. Never publish an email address, Glama session token, GitHub token, or connector credential as ownership proof.
If verification fails, confirm that you copied the current token exactly. The HTTP file must be public, return valid JSON with a successful HTTP response, and stay on the connector's origin. DNS changes may need more time to propagate. A claim cannot transfer to a different origin or hostname: if the connector target changes, Glama starts the grace period and the new target must be claimed separately after the previous claim is released.
For a connector linked to the official MCP Registry, registry updates continue to replace its name, description, and URL by default. After claiming, open Manage connector and enable Use Glama listing details as the source of truth if edits made on Glama should be preserved. Categories and thumbnails are always managed on Glama; registry linkage and technical connection settings continue to sync.
Control your server's listing on Glama, including description and metadata
Access analytics and receive server usage reports
Get monitoring and health status updates for your server
Feature your server to boost visibility and reach more users
To improve your MCP server's ranking:
Claim ownership of the server listing
Complete the server profile with an accurate description and thumbnail
Provide a test profile so Glama can connect to and evaluate the server
Keep tool definitions clear and complete to earn a high Tool Definition Quality Score (TDQS)
Route real usage through the Glama Gateway; more recorded successful server uses also improve the ranking
For users:
Full audit trail – every tool call is logged with inputs and outputs for compliance and debugging
Granular tool control – enable or disable individual tools per connector to limit what your AI agents can do
Centralized credential management – store and rotate API keys and OAuth tokens in one place
Change alerts – get notified when a connector changes its schema, adds or removes tools, or updates tool definitions, so nothing breaks silently
For server owners:
Proven adoption – public usage metrics on your listing show real-world traction and build trust with prospective users
Tool-level analytics – see which tools are being used most, helping you prioritize development and documentation
Direct user feedback – users can report issues and suggest improvements through the listing, giving you a channel you would not have otherwise
The connector status is unhealthy when Glama is unable to successfully connect to the server. This can happen for several reasons:
The server is experiencing an outage
The URL of the server is wrong
Credentials required to access the server are missing or invalid
If you are the owner of this MCP connector and would like to make modifications to the listing, including providing test credentials for accessing the server, please contact support@glama.ai.
Discussions
No comments yet. Be the first to start the discussion!
Related MCP Connectors
OpenFDA MCP — wraps the openFDA API (free, no auth required)
Search FDA safety data: drug adverse events, recalls, and device events.
FDA medical-device regulatory intelligence from keyless openFDA datasets.
Query SEC EDGAR filings, XBRL financials, and company data through MCP. STDIO & Streamable HTTP.
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceSearch and retrieve US consumer product recalls from the CPSC (Consumer Product Safety Commission) via MCP, with STDIO or Streamable HTTP.1071Apache 2.0
- FlicenseNot gradedqualityDmaintenanceEnables querying FDA drug approvals, device clearances (510(k)), recalls, and adverse events via the openFDA API, providing tools for clinical and pharmaceutical research.1
- AlicenseNot gradedqualityAmaintenanceQuery FEMA disaster declarations, public assistance grants, housing aid, and NFIP flood insurance claims via MCP. Supports STDIO and Streamable HTTP.2841Apache 2.0
- FlicenseNot gradedqualityDmaintenanceEnables searching FDA food recalls and adverse event reports through natural language, supporting filters and pagination.
Glama MCP Gateway
Add one secure layer between your agents and this server.
TDQS
Each tool targets a distinct FDA endpoint or analytic function. Search tools are separated by domain (adverse events, animal events, recalls, tobacco, etc.), and utility tools (count_values, describe_fields, dataframe_describe/query, drug_profile) serve unique purposes without overlap. An agent can clearly identify which tool to call for a given task.
All tools follow a consistent openfda_<action>_<object> pattern in snake_case. Search tools use search_<domain>, while utility tools use clear verbs like get, lookup, count, describe, and query. The only slight deviation is drug_profile (a noun phrase), but it remains intuitive and fits the naming style.
With 14 tools, the server is well-scoped for its purpose of providing access to multiple openFDA endpoints. Each tool covers a distinct resource or analytic capability, and none feel redundant. The count sits comfortably within the ideal range for a domain-specific server.
The server covers the major openFDA data categories: adverse events (human/animal), device clearances, drug approvals, shortages, recalls, tobacco, labels, and NDC lookup. It also provides robust analytics via count_values and dataframe queries, plus field discovery. There are no obvious gaps for the stated domain, and the composite drug_profile fills integration needs.