Skip to main content
Glama

🧪 MCP OpenFoodTox

Accessing EFSA's Chemical Hazards Database using natural language

A Model Context Protocol (MCP) providing access to EFSA's comprehensive OpenFoodTox database containing 8,006 chemical substances, 45,582 alternative names, and 54,621 study records from 2,437 scientific assessments across 8 interconnected data tables with over 138,000 entries.

This OpenFoodTox MCP server uses the latest EFSA dataset (updated 14 September 2023) (OpenFoodTox, data report, Zenodo) and addresses the critical need for accessible chemical safety data by consolidating EFSA's authoritative risk assessments of regulated food products, contaminants, pesticides, and feed additives. Unlike hard to use toxicological databases and spreadsheets scattered across various sources, OpenFoodTox provides structured hazard characterization data—including 11,357 risk assessments (ADI/TDI values), 11,698 toxicity endpoints (NOAEL, LD50), and 246 genotoxicity studies. This MCP makes EFSA's scientifically validated safety assessments readily available through natural language queries (via a large language model such as Claude Deesktop) for scientists, regulators, food manufacturers, and public health stakeholders.

Related MCP server: Open Food Facts MCP Server

🛠️ Tools

  • Search Substance - Find substances by name, E-number, or description. Answers: "What is [substance]?"

  • Get Substance Safety Assessment - Get safety flags (mutagenic, genotoxic, carcinogenic) for a substance. Answers: "Is [substance] safe?"

  • Get Toxicity Endpoints - Get toxicity study data including NOAEL, LD50, and target organs. Answers: "What are the toxicity effects of [substance]?"

  • Get Risk Assessments - Get safe intake limits (ADI/TDI values) and safety factors. Answers: "How much [substance] is safe daily?"

  • Get Genotoxicity Details - Get detailed genotoxicity study information including test guidelines and results. Answers: "Is [substance] genotoxic?"

  • Get Opinions - Retrieve EFSA opinion documents with publication dates, DOIs, and regulation information. Answers: "What EFSA opinions exist for [substance]?"

  • List Substances by Class and Safety - Filter substances by category (food additive, pesticide, etc.) and safety criteria. Answers: "List all [category] substances" or "Show me carcinogenic food additives"

  • List Substances by Assessment - Find substances matching specific risk assessment criteria (ADI/TDI ranges, assessment types, population groups). Answers: "List substances with ADI > 5 mg/kg" or "Find substances assessed for children"

🧾 Data Attribution

This project uses data from EFSA OpenFoodTox, the European Food Safety Authority’s chemical hazards database. Data source:

European Food Safety Authority (EFSA). OpenFoodTox – The EFSA Chemical Hazards Database. Zenodo, DOI: 10.5281/zenodo.8120114 . © European Food Safety Authority. Licensed under Creative Commons Attribution 4.0 International (CC BY 4.0) .

Official EFSA dataset page: https://www.efsa.europa.eu/en/data-report/chemical-hazards-database-openfoodtox

Disclaimer: OpenFoodTox compiles toxicological reference values and hazard data extracted from EFSA’s scientific opinions. The dataset is provided for transparency and research purposes; for regulatory or legal use, always consult the original EFSA scientific outputs.

📋 Requirements

⚡ Quick Installation in 2 steps

  1. Create virtual environment, install dependencies and setup the database (required on first run)

make setup

No virtual environment activation is required

  1. Install MCP server in Claude Desktop (optional)

# Automated installation
make claude

If you prefer to install manually, add to Claude Desktop user -> settings -> Developer -> Local MCP servers -> Edit Config:

{
  "mcp-openfoodtox": {
    "command": "absolute/path/to/mcp-openfoodtox/.venv/bin/python",
    "args": ["absolute/path/to/mcp-openfoodtox/main.py"]
  }
}

The config file location:

  • macOS: ~/Library/Application Support/Claude/claude_desktop_config.json

  • Windows: %APPDATA%/Claude/claude_desktop_config.json

  • Linux: ~/.config/Claude/claude_desktop_config.json

📦 Prerequisites Installation Details

📦 Install uv

Mac/Linux

curl -LsSf https://astral.sh/uv/install.sh | sh

Or via HomeBrew (Mac)

brew install uv

Windows

winget install astral-sh.uv

🐍 Install Python 3.12+

uv python install 3.12

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

Copyright (c) 2025 Spyros Zevelakis, Phoebe AI Limited

This software is open source and available under the MIT License.

Available Tools

9 tools
get_genotox_detailsA
Get genotoxicity study details from GENOTOX table by GENOTOX_ID.

Retrieves detailed genotoxicity study records including test methods, guidelines,
and results. This tool provides the experimental data used to assess whether
substances have genotoxic or mutagenic properties that could cause DNA damage.

Args:
    genotox_id: Single GENOTOX_ID (int) or list of GENOTOX_IDs (list[int]) to query.
               Use search_substance tool first to find GENOTOX_IDs through the STUDY table.

Returns:
    JSON string containing a DataFrame with genotoxicity study records. Each record
    includes study category, test guidelines, species, exposure conditions, and
    genotoxicity results.

The returned data includes:
- Study category: STUDY_CATEGORY
- Test guidelines: GENOTOXGUIDELINE, GENOTOXGUIDELINEFULLTXT
- Test conditions: SPECIES, STRAIN, SEX, ROUTE, EXP_PERIOD, EXPPERIODUNIT
- Genotoxicity result: IS_GENOTOXIC
- Study quality: GLP_COMPL, DEVIATION
- Study details: NUMBER_INDIVIDUALS, CONTROL, MET_INDICATOR, REMARKS

Note: Multiple records may be returned if multiple GENOTOX_IDs are provided.
Genotoxicity studies are critical for assessing cancer risk and mutagenic potential.

<dictionary_descriptions>
<name>STUDY_CATEGORY</name>
<description>Mutagenicity or genotoxicity study</description>
<name>SPECIES</name>
<description>Description of the organism/cell culture tested</description>
<name>SEX</name>
<description>Sex of the tested animals in vivo genotoxicity study</description>
<name>ROUTE</name>
<description>Description of the route of administration</description>
<name>NUMBER_INDIVIDUALS</name>
<description>Number of organisms dosed at each dose level of the in vivo genotoxicty study</description>
<name>CONTROL</name>
<description>Indicates whether and what type of concurrent control groups were used in in vivo genotoxicity study</description>
<name>IS_GENOTOXIC</name>
<description>Positive or negative result</description>
<name>REMARKS</name>
<description>Remarks on genotoxicity study</description>
</dictionary_descriptions>
ParametersJSON Schema
NameRequiredDescriptionDefault
genotox_idYes

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes the tool's behavior: it retrieves detailed records, can handle single or multiple IDs, returns JSON with a DataFrame structure, and notes that multiple records may be returned for multiple IDs. It lacks explicit details on error handling or rate limits, but covers core operational aspects well.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections (purpose, args, returns, data fields, notes) and uses bullet points for readability. It is appropriately sized for the complexity, though the dictionary descriptions section is somewhat redundant with the earlier bullet points, slightly reducing efficiency.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (1 parameter with 0% schema coverage, no annotations, no output schema), the description is highly complete. It covers purpose, usage, parameters, return format, detailed field explanations, and operational notes. The dictionary descriptions provide additional semantic clarity, ensuring the agent has all necessary context to use the tool effectively.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema description coverage is 0%, so the description must fully compensate. It provides detailed parameter semantics: explains that 'genotox_id' can be a single integer or list of integers, clarifies its purpose (querying by GENOTOX_ID), and includes usage context (finding IDs via search_substance). This adds substantial meaning beyond the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool 'retrieves detailed genotoxicity study records' from the GENOTOX table by GENOTOX_ID, specifying the exact resource and action. It distinguishes itself from sibling tools like 'search_substance' by focusing on detailed study data rather than substance searching or listing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly provides usage guidance: it instructs to 'Use search_substance tool first to find GENOTOX_IDs through the STUDY table,' naming a specific alternative tool for prerequisite steps. This gives clear context on when and how to use this tool in relation to siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_opinionsA
Get EFSA opinion documents from OPINION table by OP_ID.

Retrieves published EFSA scientific opinions, assessments, and regulatory documents.
This tool provides access to the original source documents that contain the full
scientific assessment and regulatory context for food safety evaluations.

Args:
    op_id: Single OP_ID (int) or list of OP_IDs (list[int]) to query.
          Use search_substance tool first to find OP_IDs through the STUDY table.

Returns:
    JSON string containing a DataFrame with opinion document records. Each record
    includes publication metadata, regulatory information, and document access details.

The returned data includes:
- Document identification: DOCUMENT_ID, OP_ID, TRX_ID
- Document type: DOCTYPE, DOCTYPE_CODE
- Publication details: TITLE, AUTHOR, PUBLICATIONDATE, ADOPTIONDATE, PUBLICATIONYEAR
- Access information: DOI, URL
- Regulatory context: REGULATION_CODE, REGULATION, REGULATIONFULLTEXT
- Ownership: OWNER

Note: Multiple records may be returned if multiple OP_IDs are provided. Each opinion
represents a published EFSA assessment document that may contain multiple substances
or studies.

<dictionary_descriptions>
<name>OP_ID</name>
<description>Unique identifier for the EFSA opinion document</description>
<name>DOCUMENT_ID</name>
<description>Unique document identifier</description>
<name>DOCTYPE</name>
<description>Type of document (e.g., "Scientific Opinion", "Statement")</description>
<name>TITLE</name>
<description>Title of the published opinion document</description>
<name>AUTHOR</name>
<description>Author(s) of the publication</description>
<name>PUBLICATIONDATE</name>
<description>Date when the document was published (format: yyyymmdd)</description>
<name>ADOPTIONDATE</name>
<description>Date when the document was adopted (format: yyyymmdd)</description>
<name>PUBLICATIONYEAR</name>
<description>Year of publication</description>
<name>DOI</name>
<description>Digital Object Identifier for the publication</description>
<name>URL</name>
<description>URL link to the published document</description>
<name>REGULATION_CODE</name>
<description>EU regulation code (e.g., "1333/2008" for food additives, "1107/2009" for pesticides)</description>
<name>REGULATION</name>
<description>Short name or description of the regulation</description>
<name>REGULATIONFULLTEXT</name>
<description>Full text description of the regulation</description>
<name>OWNER</name>
<description>Organization or entity that owns or published the document</description>
</dictionary_descriptions>
ParametersJSON Schema
NameRequiredDescriptionDefault
op_idYes

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes the tool's behavior: it retrieves published documents, explains the return format (JSON string containing DataFrame), details what data is included, and notes that multiple records may be returned for multiple OP_IDs. It doesn't mention performance characteristics like rate limits or error handling, but covers core operational behavior well.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections (purpose, args, returns, data details) and uses bullet points effectively. While comprehensive, it maintains focus with minimal redundancy. The dictionary descriptions section is extensive but organized, though it could be slightly more concise for a tool description.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (1 parameter but extensive return data), no annotations, and no output schema, the description provides exceptional completeness. It covers purpose, usage workflow, parameter semantics, return format, detailed field descriptions, and behavioral notes about multiple records. This fully compensates for the lack of structured metadata.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema description coverage is 0%, so the description must fully compensate. It provides comprehensive parameter semantics: explains op_id accepts single integer or list of integers, clarifies it's the unique identifier for EFSA opinion documents, and provides workflow guidance about finding OP_IDs through the STUDY table. The dictionary descriptions section further elaborates on all related fields, adding significant value beyond the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose with specific verbs ('Get', 'Retrieves') and resources ('EFSA opinion documents from OPINION table by OP_ID'), distinguishing it from siblings like search_substance (which finds OP_IDs) and other data retrieval tools. It explicitly mentions the source table and key identifier.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use this tool versus alternatives: 'Use search_substance tool first to find OP_IDs through the STUDY table.' This clearly directs users to a specific sibling tool for prerequisite steps, establishing a workflow context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_risk_assessmentsA
Get risk assessment data from CHEM_ASSESS table by HAZARD_ID.

Retrieves comprehensive risk assessment records including ADI (Acceptable Daily Intake),
TDI (Tolerable Daily Intake), and other safety limit values. This tool provides the
quantitative safety assessments used by EFSA to establish safe intake levels for
food substances.

Args:
    hazard_id: Single HAZARD_ID (int) or list of HAZARD_IDs (list[int]) to query.
              Use search_substance tool first to find HAZARD_IDs through the STUDY table.

Returns:
    JSON string containing a DataFrame with risk assessment records. Each record
    includes assessment type, risk values, units, safety factors, and population
    information.

The returned data includes:
- Assessment type: ASSESSMENTTYPE (e.g., ADI, TDI, ARfD)
- Risk values: RISKVALUE, RISKVALUE_MILLI, RISKUNIT, RISKUNIT_MILLI
- Risk qualifier: RISKQUALIFIER (e.g., "not specified", "group")
- Safety factors: SAFETY_FACTOR
- Population: ID_POPULATION, POPULATIONTEXT
- Assessment details: ASSESS, REMARKS
- Group assessments: COM_GROUP_ID, GROUP_UNIT, GROUP_REMARKS

Note: Multiple records may be returned if multiple HAZARD_IDs are provided or if
a single hazard has multiple assessment types (e.g., both ADI and TDI).

<dictionary_descriptions>
<name>RISKQUALIFIER</name>
<description>Description of the qualifier for the reference value</description>
<name>RISKVALUE</name>
<description>Quantification of the reference value</description>
<name>RISKUNIT</name>
<description>Short description of the units of the reference value</description>
<name>RISKUNITFULLTEXT</name>
<description>Full description of the units of the reference value</description>
<name>RISKVALUE_MILLI</name>
<description>Full description of the units of the reference value when converted to milligrams</description>
<name>RISKUNIT_MILLI</name>
<description>Quantification of the reference value when converted to milligrams</description>
<name>SAFETY_FACTOR</name>
<description>Safety factor/Uncertainty factor used to derive the reference value</description>
<name>POPULATIONTEXT</name>
<description>Description of the population the reference value applies to</description>
<name>REMARKS</name>
<description>General comments</description>
<name>ASSESS</name>
<description>Assessment summarised where no reference value is set</description>
</dictionary_descriptions>
ParametersJSON Schema
NameRequiredDescriptionDefault
hazard_idYes

TDQS

A4.2/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It describes the return format (JSON string with DataFrame) and notes that multiple records may be returned for multiple HAZARD_IDs or multiple assessment types. However, it lacks details on permissions, rate limits, error handling, or data freshness, which are important for a read operation with no annotation coverage.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured and front-loaded with the core purpose, followed by detailed sections on arguments, returns, and notes. However, the inclusion of the lengthy <dictionary_descriptions> section adds redundancy, as it repeats field details that could be inferred from the return description, slightly reducing conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (1 parameter, no output schema, no annotations), the description is mostly complete. It covers purpose, usage, parameters, and return format in detail. The main gap is the lack of behavioral context like error handling or performance, but it compensates with rich parameter and output explanations, making it adequate for agent use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds significant meaning beyond the input schema, which has 0% description coverage. It explains that 'hazard_id' can be a single integer or list of integers, and provides context on how to obtain these IDs via the 'search_substance' tool. This compensates fully for the schema's lack of parameter descriptions, making the semantics clear and actionable.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Get risk assessment data from CHEM_ASSESS table by HAZARD_ID' with specific details about retrieving comprehensive records including ADI, TDI, and safety limit values. It distinguishes from siblings by specifying the exact table and data type, unlike tools like 'get_genotox_details' or 'search_substance'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear usage guidance: 'Use search_substance tool first to find HAZARD_IDs through the STUDY table,' which explicitly directs to a sibling tool for prerequisite steps. However, it does not specify when to use this tool versus alternatives like 'get_substance_safety_assessment' or 'list_hazard_ids_by_assessment,' missing explicit exclusions or comparisons.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_substance_safety_assessmentA
Get comprehensive safety assessment data for a substance by SUB_COM_ID.

Retrieves safety flags (mutagenic, genotoxic, carcinogenic) and assessment metadata
from EFSA opinions, sorted chronologically by publication date. This tool provides
the core safety information used by EFSA to evaluate food safety risks.

Args:
    sub_com_id (int): The SUB_COM_ID identifier for the substance component.
                      Use search_substance tool first to find the SUB_COM_ID for a
                      given substance name or E-number.

Returns:
    JSON string containing a DataFrame with safety assessment records. Each record
    includes safety flags, classification, opinion metadata, and publication dates.
    Results are sorted chronologically (oldest to newest) by PUBLICATIONDATE.

The returned data includes:
- Safety flags: IS_MUTAGENIC, IS_GENOTOXIC, IS_CARCINOGENIC
- Classification: SUB_OP_CLASS (e.g., food additive, pesticide, flavoring)
- Study details: REMARKS_STUDY, TOXREF_ID
- Opinion metadata: OP_ID, AUTHOR, TITLE, ADOPTIONDATE, PUBLICATIONDATE

Note: Multiple records may be returned if the substance has been assessed in
multiple EFSA opinions over time. Review the chronological order to see how
safety assessments have evolved.

<dictionary_descriptions>
<name>OP_ID</name>
<description>Unique identifier links to the OPINION table</description>
<name>IS_GENOTOXIC</name>
<description>Indicates whether the substance is genotoxic or not according to the assessment provided in the opinion. The Not applicable notation is used in case of group substances</description>
<name>SUB_OP_CLASS</name>
<description>Indicates the class of the substance and the corresponding opinion as provided by EFSA</description>
<name>IS_MUTAGENIC</name>
<description>Indicates whether the substance is mutagenic or not according to the assessment provided in the opinion.  The "Not applicable" notation is used in case of group substances</description>
<name>IS_CARCINOGENIC</name>
<description>Indicates whether the substance is carcinogenic or not according to the assessment provided in the opinion. The Not applicable notation is used in case of group substances</description>
<name>REMARKS_STUDY</name>
<description>Indicates the objective of the opinion and report any general remark as retrieved from the opinion</description>
<name>TOXREF_ID</name>
<description>Unique identifier links to the ENDPOINTSTUDY table for groups</description>
<name>AUTHOR</name>
<description>Indicates the author/s of the publication</description>
<name>TITLE</name>
<description>Indicates the title of the publication</description>
<name>ADOPTIONDATE</name>
<description>Complete date of the adoption of the document in the format yyyymmdd</description>
<name>PUBLICATIONDATE</name>
<description>Complete date of the publication of the document in the format yyyymmdd</description>
</dictionary_descriptions>
ParametersJSON Schema
NameRequiredDescriptionDefault
sub_com_idYes

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes the tool's behavior: retrieving safety assessment data, sorting chronologically, returning JSON with DataFrame structure, and handling multiple records for substances assessed over time. It covers the core functionality well, though it doesn't mention potential limitations like rate limits, error conditions, or data freshness.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections: purpose statement, parameter guidance, return format explanation, and field descriptions. While comprehensive, it could be more concise by integrating the dictionary_descriptions more efficiently rather than listing them separately. The core information is front-loaded effectively.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of safety assessment data, no annotations, and no output schema, the description provides excellent completeness. It explains what data is returned, the structure (JSON DataFrame), sorting behavior, field meanings, and the possibility of multiple records. The dictionary_descriptions section provides detailed field semantics, making this description self-contained despite the lack of structured metadata.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage (the schema only shows 'sub_com_id' as a string type without description), the description fully compensates by explaining the parameter's purpose: 'The SUB_COM_ID identifier for the substance component' and providing guidance on how to obtain it via the search_substance tool. This adds crucial semantic meaning beyond the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Get comprehensive safety assessment data for a substance by SUB_COM_ID' with specific details about retrieving safety flags and assessment metadata from EFSA opinions. It distinguishes from siblings by specifying this is for safety assessment data, unlike tools like 'search_substance' (for finding IDs) or 'get_toxicity_endpoints' (for different data types).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use this tool: 'Use search_substance tool first to find the SUB_COM_ID for a given substance name or E-number.' This clearly establishes a prerequisite workflow and distinguishes it from the search_substance sibling tool. The description also explains when multiple records are returned, helping users understand the output context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_toxicity_endpointsA
Get toxicity endpoint study data from ENDPOINT_STUDY table by TOX_ID.

Retrieves detailed toxicity endpoint records including NOAEL, LD50, and other
toxicity measurements from animal and in vitro studies. This tool provides the
experimental data used to assess the toxicological effects of food substances.

Args:
    tox_id: Single TOX_ID (int) or list of TOX_IDs (list[int]) to query.
           Use search_substance tool first to find TOX_IDs through the STUDY table.

Returns:
    JSON string containing a DataFrame with toxicity endpoint records. Each record
    includes endpoint type, toxicity values, study conditions, and target organs.

The returned data includes:
- Endpoint information: ENDPOINT, ENDPOINT_CODE (e.g., NOAEL, LD50, LOAEL)
- Toxicity values: VALUE, VALUE_MILLI, DOSEUNIT, DOSEUNITFULLTEXT
- Qualifier: QUALIFIER (e.g., "greater than", "less than")
- Study conditions: SPECIES, STRAIN, SEX, ROUTE, EXP_DURATION, DURATIONUNIT
- Target information: TARGETTISSUE, EFFECT_DESC
- Toxicity classification: TOXICITY (e.g., "acute", "chronic")
- Study details: TESTTYPE, GUIDELINE, GLP_COMPL, REMARKS

Note: Multiple records may be returned if multiple TOX_IDs are provided or if
a single study has multiple endpoints measured.

<dictionary_descriptions>
<name>STUDY_CATEGORY</name>
<description>Indicates the reason for testing Human health, Exotoxicology, Animal health (target) or Animal health (non target)</description>
<name>TESTSUBSTANCE</name>
<description>Description of the test material used in the toxocological study</description>
<name>TESTTYPE_CODE</name>
<description>Transmission code for the type of toxicological test</description>
<name>SPECIES_ID</name>
<description>Internal unique identifier of organism/cell culture used in the toxicological study</description>
<name>SPECIES</name>
<description>Description of the organism/cell culture used in the toxicological study</description>
<name>SEX</name>
<description>Indicates the sex of tested animals</description>
<name>NUMBER_INDIVIDUALS</name>
<description>Number of organisms dosed at each dose level of the toxicological study</description>
<name>CONTROL</name>
<description>Indicates whether and what type of concurrent control groups were used</description>
<name>EFFECT_DESC</name>
<description>Description of the effects observed in the toxicological study</description>
<name>REMARKS</name>
<description>Additional remarks on toxicological study. Free text on hazard assessment including (if necessary): 1) short explanation on how the study has been carried on; 2) any conclusions on the hazard identication (for example, explanation on why an hazard could not be identified)</description>
</dictionary_descriptions>
ParametersJSON Schema
NameRequiredDescriptionDefault
tox_idYes

TDQS

A4.4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries full burden and does well by disclosing key behavioral traits: it describes the return format ('JSON string containing a DataFrame'), explains that multiple records may be returned for multiple TOX_IDs or multiple endpoints, and provides extensive details about what data fields are included. It doesn't mention rate limits, authentication needs, or error handling, but covers the core behavior comprehensively.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately front-loaded with purpose and usage, but becomes verbose with the extensive field listing and dictionary descriptions section. While informative, the dictionary descriptions could be streamlined or moved elsewhere as they add bulk without being essential for tool selection. The core description earns its place, but the appendix-like section reduces conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (toxicity data retrieval), no annotations, no output schema, and 0% schema coverage, the description is remarkably complete. It covers purpose, usage, parameters, return format, data structure, and even includes field definitions. For a tool with no structured metadata support, this provides all necessary context for an agent to understand and use the tool effectively.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage for the single parameter, the description fully compensates by providing rich semantic information: it explains that 'tox_id' can be 'Single TOX_ID (int) or list of TOX_IDs (list[int]) to query' and clarifies that TOX_IDs come from the STUDY table via the search_substance tool. This adds significant meaning beyond the bare schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Get toxicity endpoint study data from ENDPOINT_STUDY table by TOX_ID' with specific details about retrieving 'detailed toxicity endpoint records including NOAEL, LD50, and other toxicity measurements from animal and in vitro studies.' It distinguishes from siblings by focusing on endpoint data rather than genotoxicity details, opinions, risk assessments, or substance searches.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use this tool: 'Use search_substance tool first to find TOX_IDs through the STUDY table.' This explicitly names an alternative tool for prerequisite steps. However, it doesn't explicitly state when NOT to use this tool or compare it to other siblings like get_genotox_details or get_risk_assessments.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_hazard_ids_by_assessmentA
Find HAZARD_IDs from risk assessments (CHEM_ASSESS table) filtered by population,
assessment type, and dosage thresholds. This tool enables discovery of substances
that have specific safety limits or restrictions for particular populations.

Use this tool to identify which substances have risk assessments matching your criteria,
then use the returned HAZARD_IDs with list_substances_by_study to get the actual
substance names and details.

## Example questions it can answer:

### Population-Specific Safety Queries
* "Which substances have safety assessments for children under 3?"
* "Find all assessments that apply to pregnant women"
* "What substances have ADI limits for infants?"
* "Show me assessments for children aged 3-10"
* "Which substances have population-specific restrictions?"

### Dosage Threshold Queries
* "Find all substances with ADI less than 1 mg/kg body weight"
* "Which assessments have very low safe intake limits (< 0.1 mg/kg)?"
* "Show me substances with TDI greater than 10 mg/kg"
* "What substances have high safe intake limits (> 100 mg/kg)?"
* "Find assessments with ADI between 0.5 and 5 mg/kg"

### Assessment Type Queries
* "Which substances have ADI (Acceptable Daily Intake) assessments?"
* "Find all TDI (Tolerable Daily Intake) assessments"
* "Show me ARfD (Acute Reference Dose) assessments"
* "What substances have group assessments?"

### Combined Population + Dosage Queries
* "Find substances with ADI < 1 mg/kg for children"
* "Which assessments for pregnant women have low safe limits?"
* "Show me substances with very restrictive limits for infants (< 0.5 mg/kg)"
* "What substances have high ADI (> 50 mg/kg) for adults?"

### Missing Data Queries
* "Which assessments have no quantitative safe intake limit set?"
* "Find substances where risk assessment exists but no ADI/TDI value is specified"
* "Show me assessments that only have qualitative assessments (no numeric limits)"

### Risk Identification Queries
* "Find all substances that indicate issues for children under 3"
* "Which assessments suggest concerns for specific populations?"
* "Show me substances with population-specific warnings"

Args:
    population_text_contains: Optional text search in POPULATIONTEXT field (case-insensitive).
                             Searches for partial matches in population descriptions.
                             Examples:
                             - "children" matches "Consumers - Children", "Consumers - Children 1-2 years", etc.
                             - "pregnant" matches "Consumers - Pregnant women >= 18 years"
                             - "infant" matches "Consumers - Infants", "Consumers - Infants 0-6 months"
                             - "adult" matches "Consumers - Adults", "Consumers - Adults >=18 years"
                             See "Population Text Reference" section below for complete list of accepted values.
    assessment_type: Optional filter by assessment type (case-insensitive partial match).
                    Examples:
                    - "ADI" matches "ADI" (Acceptable Daily Intake)
                    - "TDI" matches "TDI" (Tolerable Daily Intake)
                    - "ARfD" matches "ARfD" (Acute Reference Dose)
                    - "group" matches group assessments
    risk_value_milli_max: Optional maximum RISKVALUE_MILLI in mg/kg body weight (inclusive, <=).
                         Use to find substances with low safe limits.
                         Examples:
                         - 1.0 for ADI < 1 mg/kg
                         - 0.1 for very restrictive limits
                         - 10.0 for moderate limits
    risk_value_milli_min: Optional minimum RISKVALUE_MILLI in mg/kg body weight (inclusive, >=).
                         Use to find substances with high safe limits.
                         Examples:
                         - 10.0 for ADI > 10 mg/kg
                         - 100.0 for very high limits
    has_no_risk_value: If True, only return HAZARD_IDs where RISKVALUE IS NULL.
                      Use to find assessments with no quantitative limit set.
                      These may have qualitative assessments in the ASSESS field instead.
    limit: Optional maximum number of HAZARD_IDs to return. Use to limit results
          for large queries. If None, returns all matching HAZARD_IDs.

Population Text Reference:
    The following are accepted POPULATIONTEXT values in the database. Use partial
    matches (case-insensitive) to search. For example, "children" will match
    "Consumers - Children", "Consumers - Children 1-2 years", etc.

    Consumers:
        - Consumers
        - Consumers - Children
        - Consumers - Infants
        - Consumers - Adults
        - Consumers - Adult women, pregnant
        - Consumers - Adult women, lactating
        - Consumers - Pregnant women >= 18 years
        - Consumers - Pregnant women >= 25 years
        - Consumers - Pregnant women 18-24 years
        - Consumers - Lactating women >= 18 years
        - Consumers - Lactating women >= 25 years
        - Consumers - Lactating women 18-24 years
        - Consumers - Premenopausal women
        - Consumers - Postmenopausal women
        - Consumers - Toddlers
        - Consumers - Adolescents
        - Consumers - Adults >=18 years
        - Consumers - Adults >= 25 years
        - Consumers - Adults 18-24 years
        - Consumers - Children 11-14 years
        - Consumers - Children 10-17 years
        - Consumers - Children 11-17 years
        - Consumers - Children 12-17 years
        - Consumers - Children 15-17 years
        - Consumers - Children 1-2 years
        - Consumers - Children 1-3 years
        - Consumers - Children 1-6 years
        - Consumers - Children 1-8 years
        - Consumers - Children 1-10 years
        - Consumers - Children 3 years
        - Consumers - Children 3-9 years
        - Consumers - Children 4-6 years
        - Consumers - Children 4-9 years
        - Consumers - Children 4-10 years
        - Consumers - Children 7-8 years
        - Consumers - Children 7-9 years
        - Consumers - Children 7-10 years
        - Consumers - Children 7-11 years
        - Consumers - Children 9-10 years
        - Consumers - Children 10 years
        - Consumers - Infants 0-6 months
        - Consumers - Infants 0-12 months
        - Consumers - Infants 6-12 months
        - Consumers - Infants 7-11 months

    Workers and Operators:
        - Workers
        - Worker - adults
        - Operators
        - Residents and bystanders
        - Residents and bystander - children

    Pets:
        - Dogs as pet
        - Cats as pet

    Poultry:
        - Poultry
        - Chicken for meat production
        - Chicken for egg production
        - Chicken for egg production - adults
        - Chicken for egg production, less than 1 year old
        - Chicken broilers, less than 1 year old
        - Turkeys
        - Turkeys for meat production
        - Turkeys for meat production, less than 1 year old
        - Turkey for reproduction
        - Guinea-fowl
        - Bird

    Pigs:
        - Pigs
        - Pigs - less than 1 year old
        - Pigs - for reproduction
        - Pigs for meat production
        - Pigs for meat production - adults
        - Pigs for meat production - less than 1 year old
        - Pigs for reproduction - adults

    Cattle:
        - Cattle
        - Cattle for meat production
        - Cattle for meat production - adults
        - Cattle for meat production - less than 1 year old
        - Cattle for milk production
        - Cattle for milk production - adults
        - Cattle for milk production - less than 1 year old
        - Cattle for reproduction
        - Cattle for reproduction - less than 1 year old
        - Young cattle of less than 1 year of age

    Sheep and Goats:
        - Sheep - unspecified
        - Sheep for milk production
        - Sheep for meat production
        - Goat

    Other Animals:
        - Fish
        - Salmons
        - Trouts
        - Rabbits
        - Rabbits for meat production
        - Horse
        - Equines
        - Rodents
        - Ruminants - unspecified

    Aquatic and Environmental:
        - Aquatic animal not used for food production - unspecified
        - Aquatic animal for food production - unspecified
        - Aquatic organisms
        - Aquatic Plants
        - Aquatic Invertebrates
        - Aquatic compartment
        - Terrestrial Plants
        - Soil compartment
        - Soil macroorganims - arthropods
        - Soil macroorganisms - earthworms

    Unspecified Categories:
        - Animal not used for food production - unspecified
        - Animal for food production - unspecified

Returns:
    JSON string containing a list of HAZARD_IDs (integers) that match the criteria.
    Returns an empty list if no assessments match.

    Example return value: "[123, 456, 789]"

Workflow:
    1. Use this tool to find HAZARD_IDs matching your criteria
    2. Use list_substances_by_study with the returned HAZARD_IDs and study_type="hazard"
       to get the actual substance names and details
    3. Optionally use get_risk_assessments with specific HAZARD_IDs for detailed
       assessment information

Example usage:
    # Find HAZARD_IDs for children with low ADI
    hazard_ids_json = list_hazard_ids_by_assessment(
        population_text_contains="children",
        assessment_type="ADI",
        risk_value_milli_max=1.0,
        limit=20
    )
    # Parse and use with list_substances_by_study
    hazard_ids = json.loads(hazard_ids_json)
    # substances = list_substances_by_study(ids=hazard_ids, study_type="hazard")
ParametersJSON Schema
NameRequiredDescriptionDefault
population_text_containsNo
assessment_typeNo
risk_value_milli_maxNo
risk_value_milli_minNo
has_no_risk_valueNo
limitNo

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes the tool's behavior: it returns HAZARD_IDs as JSON strings, explains case-insensitive partial matching for text fields, clarifies inclusive thresholds for numeric filters, documents the 'has_no_risk_value' parameter for finding assessments without quantitative limits, and specifies that it returns an empty list for no matches. The description also includes a comprehensive 'Population Text Reference' section, which is valuable context beyond basic parameter documentation.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections (purpose, usage guidance, example questions, parameter details, reference, returns, workflow, example), but it is quite lengthy due to the extensive parameter documentation and reference list. While every section adds value, the sheer volume might be overwhelming. However, the front-loaded purpose and usage guidelines are effective, and the structure aids readability.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (6 parameters, no annotations, no output schema), the description is highly complete. It covers purpose, usage guidelines, detailed parameter semantics with examples, return format, workflow integration with sibling tools, and even includes a comprehensive reference section. The description fully compensates for the lack of structured metadata, making the tool's functionality and context clear.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema description coverage is 0%, so the description must fully compensate. It does so excellently: each parameter is documented with clear explanations, examples, and usage guidance. For instance, 'population_text_contains' includes a detailed reference list of accepted values with partial matching rules, 'risk_value_milli_max/min' explain the units (mg/kg) and inclusive thresholds, and 'has_no_risk_value' clarifies its purpose for finding qualitative assessments. The description adds substantial meaning beyond what the bare schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Find HAZARD_IDs from risk assessments (CHEM_ASSESS table) filtered by population, assessment type, and dosage thresholds.' It specifies the verb ('Find'), resource ('HAZARD_IDs'), source table ('CHEM_ASSESS'), and filtering criteria. It distinguishes from siblings by focusing on hazard IDs rather than substances or detailed assessments.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use this tool versus alternatives. It states: 'Use this tool to identify which substances have risk assessments matching your criteria, then use the returned HAZARD_IDs with list_substances_by_study to get the actual substance names and details.' It also includes a 'Workflow' section detailing step-by-step usage with sibling tools, making the tool's role in the overall process clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_substances_by_assessmentA
Find substances from risk assessments (CHEM_ASSESS table) filtered by population,
assessment type, and dosage thresholds. This tool combines two queries:
1. Filters CHEM_ASSESS to find matching HAZARD_IDs
2. Retrieves substances associated with those HAZARD_IDs

This tool enables discovery of substances that have specific safety limits or
restrictions for particular populations, returning the actual substance names
and details directly.

## Example questions it can answer:

### Population-Specific Safety Queries
* "Which substances have safety assessments for children under 3?"
* "Find all assessments that apply to pregnant women"
* "What substances have ADI limits for infants?"
* "Show me assessments for children aged 3-10"
* "Which substances have population-specific restrictions?"

### Dosage Threshold Queries
* "Find all substances with ADI less than 1 mg/kg body weight"
* "Which assessments have very low safe intake limits (< 0.1 mg/kg)?"
* "Show me substances with TDI greater than 10 mg/kg"
* "What substances have high safe intake limits (> 100 mg/kg)?"
* "Find assessments with ADI between 0.5 and 5 mg/kg"

### Assessment Type Queries
* "Which substances have ADI (Acceptable Daily Intake) assessments?"
* "Find all TDI (Tolerable Daily Intake) assessments"
* "Show me ARfD (Acute Reference Dose) assessments"
* "What substances have group assessments?"

### Combined Population + Dosage Queries
* "Find substances with ADI < 1 mg/kg for children"
* "Which assessments for pregnant women have low safe limits?"
* "Show me substances with very restrictive limits for infants (< 0.5 mg/kg)"
* "What substances have high ADI (> 50 mg/kg) for adults?"

### Missing Data Queries
* "Which assessments have no quantitative safe intake limit set?"
* "Find substances where risk assessment exists but no ADI/TDI value is specified"
* "Show me assessments that only have qualitative assessments (no numeric limits)"

### Risk Identification Queries
* "Find all substances that indicate issues for children under 3"
* "Which assessments suggest concerns for specific populations?"
* "Show me substances with population-specific warnings"

Args:
    population_text_contains: Optional text search in POPULATIONTEXT field (case-insensitive).
                             Searches for partial matches in population descriptions.
                             Examples:
                             - "children" matches "Consumers - Children", "Consumers - Children 1-2 years", etc.
                             - "pregnant" matches "Consumers - Pregnant women >= 18 years"
                             - "infant" matches "Consumers - Infants", "Consumers - Infants 0-6 months"
                             - "adult" matches "Consumers - Adults", "Consumers - Adults >=18 years"
                             See "Population Text Reference" section below for complete list of accepted values.
    assessment_type: Optional filter by assessment type (case-insensitive partial match).
                    Examples:
                    - "ADI" matches "ADI" (Acceptable Daily Intake)
                    - "TDI" matches "TDI" (Tolerable Daily Intake)
                    - "ARfD" matches "ARfD" (Acute Reference Dose)
                    - "group" matches group assessments
    risk_value_milli_max: Optional maximum RISKVALUE_MILLI in mg/kg body weight (inclusive, <=).
                         Use to find substances with low safe limits.
                         Examples:
                         - 1.0 for ADI < 1 mg/kg
                         - 0.1 for very restrictive limits
                         - 10.0 for moderate limits
    risk_value_milli_min: Optional minimum RISKVALUE_MILLI in mg/kg body weight (inclusive, >=).
                         Use to find substances with high safe limits.
                         Examples:
                         - 10.0 for ADI > 10 mg/kg
                         - 100.0 for very high limits
    has_no_risk_value: If True, only return HAZARD_IDs where RISKVALUE IS NULL.
                      Use to find assessments with no quantitative limit set.
                      These may have qualitative assessments in the ASSESS field instead.
    limit: Maximum number of substances to return (default: 10). This limits the final
          substance results after filtering by assessment criteria.

Population Text Reference:
    The following are accepted POPULATIONTEXT values in the database. Use partial
    matches (case-insensitive) to search. For example, "children" will match
    "Consumers - Children", "Consumers - Children 1-2 years", etc.

    Consumers:
        - Consumers
        - Consumers - Children
        - Consumers - Infants
        - Consumers - Adults
        - Consumers - Adult women, pregnant
        - Consumers - Adult women, lactating
        - Consumers - Pregnant women >= 18 years
        - Consumers - Pregnant women >= 25 years
        - Consumers - Pregnant women 18-24 years
        - Consumers - Lactating women >= 18 years
        - Consumers - Lactating women >= 25 years
        - Consumers - Lactating women 18-24 years
        - Consumers - Premenopausal women
        - Consumers - Postmenopausal women
        - Consumers - Toddlers
        - Consumers - Adolescents
        - Consumers - Adults >=18 years
        - Consumers - Adults >= 25 years
        - Consumers - Adults 18-24 years
        - Consumers - Children 11-14 years
        - Consumers - Children 10-17 years
        - Consumers - Children 11-17 years
        - Consumers - Children 12-17 years
        - Consumers - Children 15-17 years
        - Consumers - Children 1-2 years
        - Consumers - Children 1-3 years
        - Consumers - Children 1-6 years
        - Consumers - Children 1-8 years
        - Consumers - Children 1-10 years
        - Consumers - Children 3 years
        - Consumers - Children 3-9 years
        - Consumers - Children 4-6 years
        - Consumers - Children 4-9 years
        - Consumers - Children 4-10 years
        - Consumers - Children 7-8 years
        - Consumers - Children 7-9 years
        - Consumers - Children 7-10 years
        - Consumers - Children 7-11 years
        - Consumers - Children 9-10 years
        - Consumers - Children 10 years
        - Consumers - Infants 0-6 months
        - Consumers - Infants 0-12 months
        - Consumers - Infants 6-12 months
        - Consumers - Infants 7-11 months

    Workers and Operators:
        - Workers
        - Worker - adults
        - Operators
        - Residents and bystanders
        - Residents and bystander - children

    Pets:
        - Dogs as pet
        - Cats as pet

    Poultry:
        - Poultry
        - Chicken for meat production
        - Chicken for egg production
        - Chicken for egg production - adults
        - Chicken for egg production, less than 1 year old
        - Chicken broilers, less than 1 year old
        - Turkeys
        - Turkeys for meat production
        - Turkeys for meat production, less than 1 year old
        - Turkey for reproduction
        - Guinea-fowl
        - Bird

    Pigs:
        - Pigs
        - Pigs - less than 1 year old
        - Pigs - for reproduction
        - Pigs for meat production
        - Pigs for meat production - adults
        - Pigs for meat production - less than 1 year old
        - Pigs for reproduction - adults

    Cattle:
        - Cattle
        - Cattle for meat production
        - Cattle for meat production - adults
        - Cattle for meat production - less than 1 year old
        - Cattle for milk production
        - Cattle for milk production - adults
        - Cattle for milk production - less than 1 year old
        - Cattle for reproduction
        - Cattle for reproduction - less than 1 year old
        - Young cattle of less than 1 year of age

    Sheep and Goats:
        - Sheep - unspecified
        - Sheep for milk production
        - Sheep for meat production
        - Goat

    Other Animals:
        - Fish
        - Salmons
        - Trouts
        - Rabbits
        - Rabbits for meat production
        - Horse
        - Equines
        - Rodents
        - Ruminants - unspecified

    Aquatic and Environmental:
        - Aquatic animal not used for food production - unspecified
        - Aquatic animal for food production - unspecified
        - Aquatic organisms
        - Aquatic Plants
        - Aquatic Invertebrates
        - Aquatic compartment
        - Terrestrial Plants
        - Soil compartment
        - Soil macroorganims - arthropods
        - Soil macroorganisms - earthworms

    Unspecified Categories:
        - Animal not used for food production - unspecified
        - Animal for food production - unspecified

Returns:
    JSON string containing a DataFrame with substance records. Each record includes
    substance identification, classification, and alternative names/E-numbers.

    The returned data includes:
    - Substance identification: SUB_COM_ID (unique identifier)
    - Chemical details: COM_NAME (chemical name), COM_TYPE (single/mixture/botanical/synthetic)
    - Classification: SUB_TYPE (substance type qualifier)
    - Alternative names: DESCRIPTION (comma-separated synonyms, E-numbers, trade names)

    Returns an empty DataFrame (as JSON) if no substances match the criteria.

    Joins: CHEM_ASSESS → STUDY (by HAZARD_ID) → COMPONENT (by SUB_COM_ID) → SYNONYM (by SUB_COM_ID)
    Returns unique substances (DISTINCT by SUB_COM_ID).

    Note: Multiple synonyms per substance are aggregated into a comma-separated list.
    Use the search_substance tool to get detailed information about specific substances
    from the results, or use get_risk_assessments with HAZARD_IDs for detailed
    assessment information.

Example usage:
    # Find substances with ADI < 1 mg/kg for children
    substances_json = list_substances_by_assessment(
        population_text_contains="children",
        assessment_type="ADI",
        risk_value_milli_max=1.0,
        limit=20
    )
ParametersJSON Schema
NameRequiredDescriptionDefault
population_text_containsNo
assessment_typeNo
risk_value_milli_maxNo
risk_value_milli_minNo
has_no_risk_valueNo
limitNo

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden and does well by disclosing key behavioral traits: it explains the two-step query process, returns a JSON string with a DataFrame, includes details on joins and uniqueness (DISTINCT by SUB_COM_ID), and notes that multiple synonyms are aggregated. However, it lacks explicit mention of potential performance impacts or error handling, which slightly limits transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with a clear purpose and usage examples, but it is overly long due to the extensive population text reference list and repetitive example questions. While informative, this reduces conciseness, as not all sentences earn their place equally; the list could be summarized more efficiently.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex tool with 6 parameters, 0% schema coverage, no annotations, and no output schema, the description is highly complete: it covers purpose, usage, parameters, returns (including data structure and joins), and provides an example usage. It effectively bridges all gaps left by the structured fields, making it self-sufficient for an agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Given 0% schema description coverage, the description fully compensates by providing detailed semantics for all 6 parameters: it explains each parameter's purpose (e.g., 'population_text_contains' for case-insensitive partial matches), includes extensive examples and a reference list for population values, clarifies units (mg/kg body weight for risk values), and describes default behavior (e.g., limit default is 10).

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose with specific verbs ('Find substances from risk assessments') and resources ('CHEM_ASSESS table'), and distinguishes it from siblings by explaining it combines two queries to retrieve substance names and details directly, unlike tools like 'get_risk_assessments' or 'search_substance' which focus on different aspects.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on when to use this tool through extensive example questions (e.g., population-specific, dosage threshold, assessment type queries) and explicitly mentions alternatives like 'search_substance' and 'get_risk_assessments' in the Returns section, clarifying when to use those instead for detailed information.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_substances_by_class_and_safetyA
Retrieves substances from the EFSA OpenFoodTox database filtered by safety assessment
criteria (mutagenicity, genotoxicity, carcinogenicity) and substance classification.
This tool enables discovery of substances based on their safety profile and regulatory
category, useful for comparative safety analysis and regulatory compliance queries.

## Example questions it can answer:
### Classification + Safety Status Queries
By category:
* "What food additives are genotoxic?"
* "List pesticides that are carcinogenic"
* "Show me flavourings that are mutagenic"
* "What sensory additives have positive genotoxicity results?"
### Safety screening:
"Which substances are both mutagenic and genotoxic?"
* "Find substances that are positive for carcinogenicity"
* "What additives have ambiguous safety data?"
* "List substances with no mutagenicity data"
### Combined filters:
* "What food additives are not genotoxic?" (Negative)
* "Show pesticides that are not carcinogenic"
* "List flavourings with ambiguous genotoxicity results"
### Regulatory & Compliance Queries
"Which food additives have positive mutagenicity assessments?"
* "What pesticides are flagged as genotoxic?"
* "List substances in the 'Food additives' category with safety concerns"
* "Show me technological additives that are not mutagenic"
### Research & Analysis Queries
* "What substances have 'reproductive' in their study remarks?"
* "Find additives with 'chronic' mentioned in remarks"
* "List substances with 'developmental' toxicity in remarks"
* "Show me substances where remarks contain 'neurotoxicity'"
### Comparative Safety Queries
* "Compare all food additives by their genotoxicity status"
* "Which category has the most substances with positive carcinogenicity?"
"List all substances with positive results in any safety category"
### Data Quality Queries
* "What substances have 'No data' for mutagenicity?"
* "Show me substances with 'Not determined' safety assessments"
* "List additives with incomplete safety data"

Args:
    sub_class: Optional SUB_OP_CLASS filter. Accepts partial matches (case-insensitive LIKE).
               Examples:
               - "additives" matches "Food additives", "Nutritional additives", "Sensory additives", etc.
               - "food" matches "Food additives", "Food contact materials"
               - "pesticides" matches "Pesticides"
               - "Food additives" (exact match also works)
               Valid full values (all possible SUB_OP_CLASS values):
               - "No category"
               - "Cocciodiostats/Hormones/Histomonostats"
               - "Persistent organic pollutants"
               - "Natural plant product contaminants"
               - "Mycotoxins"
               - "Melamine"
               - "Processing contaminants"
               - "Marine biotoxins"
               - "Heavy metal ions and metalloids"
               - "Nutritional additives"
               - "Sensory additives"
               - "Technological additives"
               - "Zootechnical additives"
               - "Feed intended for particular nutritional purposes"
               - "Food additives"
               - "Food contact materials"
               - "Processing aids"
               - "Nutrient sources"
               - "Pesticides"
               - "Flavourings"
    is_mutagenic: Optional IS_MUTAGENIC filter (exact match: "Positive", "Negative", "Ambiguous", etc.)
    is_genotoxic: Optional IS_GENOTOXIC filter (exact match: "Positive", "Negative", "Ambiguous", etc.)
    is_carcinogenic: Optional IS_CARCINOGENIC filter (exact match: "Positive", "Negative", "Ambiguous", etc.)
    remarks_contains: Optional text search in REMARKS_STUDY (case-insensitive LIKE, substring match)
    limit: Maximum number of results to return (default: 10)

Returns:
    JSON string containing a DataFrame with substance records. Each record includes
    substance identification, classification, and alternative names/E-numbers.
    The function also returns a total_count indicating how many substances match
    the criteria before the limit is applied.

The returned data includes:
- Substance identification: SUB_COM_ID (unique identifier)
- Chemical details: COM_NAME (chemical name), COM_TYPE (single/mixture/botanical/synthetic)
- Classification: SUB_TYPE (substance type qualifier)
- Alternative names: DESCRIPTION (comma-separated synonyms, E-numbers, trade names)

Joins: STUDY → COMPONENT (by SUB_COM_ID) → SYNONYM (by SUB_COM_ID)
Returns unique substances (DISTINCT by SUB_COM_ID).

Note: Multiple synonyms per substance are aggregated into a comma-separated list.
Use the search_substance tool to get detailed information about specific substances
from the results.
ParametersJSON Schema
NameRequiredDescriptionDefault
sub_classNo
is_mutagenicNo
is_genotoxicNo
is_carcinogenicNo
remarks_containsNo
limitNo

TDQS

A4.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes key behaviors: it's a read-only retrieval tool (implied by 'retrieves'), specifies data source (EFSA OpenFoodTox database), explains result format (JSON string with DataFrame), includes pagination behavior via 'limit' parameter, describes data joins and uniqueness (DISTINCT by SUB_COM_ID), and mentions aggregation of synonyms. However, it doesn't cover potential rate limits, authentication requirements, or error conditions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with clear sections (purpose, examples, parameters, returns, notes) but is excessively long due to the extensive example questions list. While the examples are helpful, they occupy disproportionate space, making the description verbose. The core information is front-loaded, but the length reduces overall conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (6 parameters, no annotations, no output schema), the description provides exceptional completeness. It covers purpose, usage scenarios, detailed parameter semantics, return format, data structure, joins, uniqueness constraints, aggregation behavior, and when to use alternative tools. For a filtering/retrieval tool with rich functionality, this description leaves no significant gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description fully compensates by providing comprehensive parameter documentation. Each parameter gets detailed explanations: 'sub_class' includes partial matching behavior, examples, and complete valid value list; safety filters specify exact match requirements and enum values; 'remarks_contains' describes substring matching; 'limit' explains default behavior. This adds substantial value beyond what the bare schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states the tool 'retrieves substances from the EFSA OpenFoodTox database filtered by safety assessment criteria and substance classification.' It specifies the exact resource (EFSA OpenFoodTox database), filtering criteria (mutagenicity, genotoxicity, carcinogenicity, classification), and distinguishes it from sibling tools like 'search_substance' by focusing on filtered discovery rather than detailed information retrieval.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides extensive usage guidance with a dedicated 'Example questions it can answer' section, covering classification+safety queries, safety screening, combined filters, regulatory compliance, research analysis, comparative safety, and data quality queries. It explicitly mentions when to use an alternative tool ('Use the search_substance tool to get detailed information about specific substances from the results'), making it clear when this tool is appropriate versus siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_substanceA
MCP tool to search the OpenFoodTox database for substances by name, E-number, or description.

Searches the database using a two-step approach:
1. First searches SYNONYM table (E-numbers, common names, trade names, alternative names)
2. If no results, searches COMPONENT table (SUB_NAME and COM_NAME fields)

The search is case-insensitive and supports partial matches. E-numbers are automatically
normalized (e.g., "E 951" or "E-951" becomes "E951").

Returns a list of unique substances (one dictionary per SUB_COM_ID) with all study data
aggregated into arrays. Each substance may have multiple studies, opinions, and assessments,
which are grouped together by SUB_COM_ID.

Args:
    description_search: Search term (substance or component name e.g. "aspartame", OR E-number e.g. "E 951") or any of the following CAS name, Council of Europe number, E number, E.C enzyme number, EC name, EU Flavour Information System number, EUgroup-no, Flavour and Extract Manufacturers Association number, Joint FAO/WHO Expert Committee on Food Additives number, Name, OECD Toolbox Classification, Pharmalogical class, Swiss Prot no., Trade name

Returns:
    List of dictionaries, where each dictionary represents a unique substance with:
    - Basic component information (name, type, formula, description)
    - Aggregated study identifiers (arrays of IDs linking to related tables)
    - Study classifications and remarks (arrays of unique values from all studies)

    Returns None if no matches are found.

<dictionary_descriptions>
<name>SUB_COM_ID</name>
<description>Unique identifier for the substance-component link. Primary key for grouping results. Multiple studies, opinions, and assessments may reference the same SUB_COM_ID.</description>
<name>COM_NAME</name>
<description>Component name as derived in the opinions. If more than one name is reported in the opinion (excluding IUPAC name), then the most common/most specific name is reported as component name.</description>
<name>COM_TYPE</name>
<description>High level classification of component type (e.g., single, mixture, botanical, synthetic).</description>
<name>MOLECULARFORMULA</name>
<description>Molecular formula of the chemical component.</description>
<name>SUB_DESCRIPTION</name>
<description>Summary of the substance description as derived from opinions. This includes also the group description.</description>
<name>SUB_OP_CLASS</name>
<description>Array of unique values indicating the class of the substance and the corresponding opinion as provided by EFSA (e.g., "food additive", "pesticide", "flavoring"). Aggregated from all studies for this substance.</description>
<name>REMARKS</name>
<description>Array of unique remarks from all studies. Indicates the objective of the opinion and reports any general remarks as retrieved from the opinion. Aggregated from REMARKS_STUDY field.</description>
<name>GENOTOX_ID</name>
<description>Array of unique identifiers linking to the GENOTOX table. Each ID represents a genotoxicity study associated with this substance. May be None if no genotoxicity studies exist.</description>
<name>TOX_ID</name>
<description>Array of unique identifiers linking to the ENDPOINT_STUDY table. Each ID represents a toxicity endpoint study (e.g., NOAEL, LD50). May be None if no endpoint studies exist.</description>
<name>HAZARD_ID</name>
<description>Array of unique identifiers linking to the CHEM_ASSESS table. Each ID represents a chemical risk assessment (e.g., ADI, TDI values). May be None if no assessments exist.</description>
<name>OP_ID</name>
<description>Array of unique identifiers linking to the OPINION table. Each ID represents an EFSA published opinion/document associated with this substance. May be None if no opinions exist.</description>
</dictionary_descriptions>
ParametersJSON Schema
NameRequiredDescriptionDefault
description_searchYes

TDQS

A4.7/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It thoroughly explains the search behavior: case-insensitive, partial matches, E-number normalization, and the two-step approach (SYNONYM then COMPONENT tables). It also details the return structure, including what happens when no matches are found (returns None) and how data is aggregated (by SUB_COM_ID). This provides comprehensive behavioral context beyond basic functionality.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured and appropriately sized, with clear sections for purpose, search behavior, parameters, returns, and dictionary descriptions. It is front-loaded with the core functionality. However, the detailed dictionary descriptions, while useful, are lengthy and could be condensed or moved to an output schema if available, slightly affecting conciseness.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity of the tool (search with data aggregation), no annotations, and no output schema, the description is highly complete. It covers purpose, search behavior, parameter details, return structure, and comprehensive field descriptions for the output. This provides all necessary context for an AI agent to understand and use the tool effectively, compensating for the lack of structured data.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema description coverage is 0%, so the description must compensate. It provides extensive parameter semantics: 'description_search' is explained as a search term for substance/component names or E-numbers, with examples ('aspartame', 'E 951') and a detailed list of what can be searched (e.g., CAS name, trade name). This adds significant meaning beyond the minimal schema, fully documenting the parameter's purpose and usage.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'search the OpenFoodTox database for substances by name, E-number, or description.' It specifies the exact resource (OpenFoodTox database) and the search criteria (name, E-number, description), distinguishing it from sibling tools that retrieve specific data types like genotoxicity details or risk assessments.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use this tool: for searching substances in the OpenFoodTox database. It explains the two-step search approach and what types of terms can be used (e.g., 'aspartame', 'E 951'). However, it does not explicitly state when to use this tool versus alternatives like 'list_substances_by_class_and_safety' or 'list_substances_by_assessment', which are sibling tools that might retrieve substances based on different criteria.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

A4.4/5.0
Disambiguation4/5

Most tools have distinct purposes targeting different data tables (genotoxicity, opinions, risk assessments, etc.), but there is some overlap between list_hazard_ids_by_assessment and list_substances_by_assessment, as both filter risk assessments by similar criteria but return different outputs (IDs vs. substances). The descriptions clarify the distinction, but an agent might initially confuse them.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern with snake_case (e.g., get_genotox_details, list_substances_by_assessment). The naming is predictable and readable, with no mixing of conventions or chaotic styles.

Tool Count5/5

With 9 tools, the count is well-scoped for a database query server covering multiple data tables and filtering options. Each tool serves a clear purpose in retrieving or listing data, and none feel redundant or excessive for the domain.

Completeness4/5

The toolset provides comprehensive coverage for querying the OpenFoodTox database, including retrieval of detailed records (get_* tools) and filtered listings (list_* tools). A minor gap is the lack of a tool for updating or deleting data, but this is reasonable for a read-only query server focused on EFSA assessments.

Maintenance

ActivityInactive
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    D
    maintenance
    Enables AI assistants to access the Open Food Facts database to query detailed food product information, nutritional data, and environmental scores. Supports product lookup by barcode, smart search with filtering, nutritional analysis, product comparison, and dietary recommendations to help users make informed food choices.
    5
    1
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables checking food additive safety, nutrition profiles, pesticide residues, and ingredient lists with regulatory flags and dietary compatibility. All data is sourced from authoritative bodies like JECFA, EFSA, and FDA.
    MIT

Appeared in Searches

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/spyrosze/mcp-openfoodtox'

If you have feedback or need assistance with the MCP directory API, please join our Discord server