Skip to main content
Glama
biocontext-ai

BioContextAI Knowledgebase MCP

Official

bc_get_generic_equivalents

Find generic drug alternatives for brand-name medications by searching ANDA entries with matching active ingredients.

Instructions

Find generic equivalents for a brand name drug. Searches ANDA entries with matching active ingredients.

Returns: dict: Brand drug info, generic_equivalents array, total_generics_found count or error message.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
brand_nameYesBrand name drug to find generics for

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The core handler function for the 'get_generic_equivalents' tool (prefixed to 'bc_get_generic_equivalents' in main app). It fetches the brand drug's active ingredients from OpenFDA and searches for matching ANDA (generic) approvals.
    @core_mcp.tool()
    def get_generic_equivalents(
        brand_name: Annotated[str, Field(description="Brand name drug to find generics for")],
    ) -> dict:
        """Find generic equivalents for a brand name drug. Searches ANDA entries with matching active ingredients.
    
        Returns:
            dict: Brand drug info, generic_equivalents array, total_generics_found count or error message.
        """
        # First, search for the brand name drug to get its active ingredient
        brand_query = f"(openfda.brand_name:{brand_name} OR products.brand_name:{brand_name})"
        base_url = "https://api.fda.gov/drug/drugsfda.json"
        brand_params: Any = {"search": brand_query, "limit": 1}
    
        try:
            brand_response = requests.get(base_url, params=brand_params)
            brand_response.raise_for_status()
            brand_data = brand_response.json()
    
            if not brand_data.get("results"):
                return {"error": f"Brand name drug '{brand_name}' not found in FDA database"}
    
            # Extract active ingredients from the brand drug
            brand_drug = brand_data["results"][0]
    
            # Check if we have products and active ingredients
            if not brand_drug.get("products"):
                return {"error": f"Could not find product information for '{brand_name}'"}
    
            # Search for generic drugs (ANDA applications) with similar active ingredients
            generic_results = []
    
            # Try to find active ingredients from the first product
            for product in brand_drug["products"][:1]:  # Just check first product
                if product.get("active_ingredients"):
                    active_ingredients = product["active_ingredients"]
    
                    # Handle case where active_ingredients might be an object or array
                    if isinstance(active_ingredients, dict):
                        ingredient_name = active_ingredients.get("name", "")
                        if ingredient_name:
                            # Search for ANDA applications with this active ingredient
                            generic_query = (
                                f"application_number:ANDA* AND products.active_ingredients.name:{ingredient_name}"
                            )
                            generic_params: Any = {"search": generic_query, "limit": 20}
    
                            try:
                                generic_response = requests.get(base_url, params=generic_params)
                                generic_response.raise_for_status()
                                generic_data = generic_response.json()
    
                                if generic_data.get("results"):
                                    generic_results.extend(generic_data["results"])
                            except requests.exceptions.RequestException:
                                continue  # Skip this ingredient if search fails
    
                    elif isinstance(active_ingredients, list):
                        for ingredient in active_ingredients:
                            if isinstance(ingredient, dict):
                                ingredient_name = ingredient.get("name", "")
                                if ingredient_name:
                                    # Search for ANDA applications with this active ingredient
                                    generic_query = (
                                        f"application_number:ANDA* AND products.active_ingredients.name:{ingredient_name}"
                                    )
                                    generic_params = {"search": generic_query, "limit": 20}
    
                                    try:
                                        generic_response = requests.get(base_url, params=generic_params)
                                        generic_response.raise_for_status()
                                        generic_data = generic_response.json()
    
                                        if generic_data.get("results"):
                                            generic_results.extend(generic_data["results"])
                                    except requests.exceptions.RequestException:
                                        continue  # Skip this ingredient if search fails
    
            return {
                "brand_drug": brand_drug,
                "generic_equivalents": generic_results,
                "total_generics_found": len(generic_results),
            }
    
        except requests.exceptions.RequestException as e:
            return {"error": f"Failed to fetch generic equivalents: {e!s}"}
  • Registers the core_mcp (name='BC') into the main mcp_app with prefix slugify('BC')='bc', making tools available as 'bc_*' including 'bc_get_generic_equivalents'.
    for mcp in [core_mcp, *(await get_openapi_mcps())]:
        await mcp_app.import_server(
            mcp,
            slugify(mcp.name),
        )
    logger.info("MCP server setup complete.")
  • Defines core_mcp FastMCP server instance named 'BC' where tools like get_generic_equivalents are decorated and registered.
    core_mcp = FastMCP(  # type: ignore
        "BC",
        instructions="Provides access to biomedical knowledge bases.",
    )
  • Pydantic schema for input: brand_name (str, required, description provided). Output: dict with brand_drug, generic_equivalents list, total_generics_found.
    def get_generic_equivalents(
        brand_name: Annotated[str, Field(description="Brand name drug to find generics for")],
    ) -> dict:
  • Exports get_generic_equivalents from _advanced_search.py for use in core_mcp.
    from ._advanced_search import (
        get_available_pharmacologic_classes,
        get_generic_equivalents,
        search_drugs_by_therapeutic_class,
    )
Behavior2/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 mentions the search scope ('ANDA entries') and return structure, but lacks details on error conditions, rate limits, authentication needs, or data freshness. For a lookup tool with zero annotation coverage, this leaves significant gaps in understanding operational behavior.

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 efficiently structured in three sentences: purpose, search method, and return format. Each sentence adds value without redundancy. However, it could be slightly more front-loaded by integrating the return details into the purpose statement for better clarity.

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

Completeness3/5

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

Given the tool's moderate complexity (single-parameter lookup), 100% schema coverage, and presence of an output schema, the description is adequate but incomplete. It covers the core purpose and return structure, but lacks usage guidelines and behavioral details that would help an agent operate it effectively in context with sibling tools.

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

Parameters3/5

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

Schema description coverage is 100%, with the single parameter 'brand_name' clearly documented in the schema. The description adds minimal value beyond the schema by implying the parameter is used to 'find generics for,' but doesn't provide additional context like format examples or search constraints. Baseline 3 is appropriate given the schema does the heavy lifting.

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

Purpose4/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 generic equivalents for a brand name drug' with the specific action 'Searches ANDA entries with matching active ingredients.' It distinguishes itself from most siblings by focusing on drug generics, though it doesn't explicitly differentiate from similar drug-related tools like bc_search_drugs_fda or bc_get_drug_label_info.

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

Usage Guidelines2/5

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

No guidance is provided on when to use this tool versus alternatives. The description doesn't mention prerequisites, limitations, or compare it to sibling tools like bc_search_drugs_fda or bc_get_drug_statistics, leaving the agent to infer usage context solely from the purpose statement.

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

Install Server

Other Tools

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/biocontext-ai/knowledgebase-mcp'

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