Skip to main content
Glama

get-drug-by-ndc

Retrieve detailed drug information from the OpenFDA database by entering a National Drug Code (NDC) in any standard format.

Instructions

Get drug information by National Drug Code (NDC). Accepts both product NDC (XXXXX-XXXX) and package NDC (XXXXX-XXXX-XX) formats. Also accepts NDC codes without dashes.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
ndcCodeYesNational Drug Code (NDC) - accepts formats: XXXXX-XXXX, XXXXX-XXXX-XX, or without dashes

Implementation Reference

  • The handler function that implements the core logic of the 'get-drug-by-ndc' tool. It normalizes the input NDC code, constructs an OpenFDA API query using product and/or package NDC, fetches the data, processes the results to extract relevant drug information and matching NDCs, and returns a formatted text response.
    async ({ ndcCode }) => {
      const { productNDC, packageNDC, isValid } = normalizeNDC(ndcCode);
      
      if (!isValid) {
        return {
          content: [{
            type: "text",
            text: `Invalid NDC format: "${ndcCode}"\n\n✅ Accepted formats:\n• Product NDC: 12345-1234\n• Package NDC: 12345-1234-01\n• Without dashes: 123451234 or 12345123401`,
          }],
        };
      }
    
      console.log(`Searching for NDC: input="${ndcCode}", productNDC="${productNDC}", packageNDC="${packageNDC}"`);
    
      // Try searching by product NDC first (most flexible)
      let searchQuery = `openfda.product_ndc:"${productNDC}"`;
      
      // If a specific package was requested, also search package NDC
      if (packageNDC) {
        searchQuery += `+OR+openfda.package_ndc:"${packageNDC}"`;
      }
    
      const url = new OpenFDABuilder()
        .context("label")
        .search(searchQuery)
        .limit(10) // Get multiple results since product NDC might have multiple packages
        .build();
    
      const { data: drugData, error } = await makeOpenFDARequest<OpenFDAResponse>(url);
      
      if (error) {
        return {
          content: [{
            type: "text",
            text: `Failed to retrieve drug data for NDC "${ndcCode}": ${error.message}`,
          }],
        };
      }
    
      if (!drugData || !drugData.results || drugData.results.length === 0) {
        return {
          content: [{
            type: "text",
            text: `No drug found with NDC "${ndcCode}" (product: ${productNDC}).\n\n💡 Tips:\n• Verify the NDC format\n• Try without the package suffix (e.g., use 12345-1234 instead of 12345-1234-01)\n• Check if this is an FDA-approved product`,
          }],
        };
      }
    
      // Process results and group by product
      const results = drugData.results.map(drug => {
        const matchingProductNDCs = drug.openfda.product_ndc?.filter(ndc => 
          ndc === productNDC
        ) || [];
        
        const matchingPackageNDCs = drug.openfda.package_ndc?.filter(ndc => 
          packageNDC ? ndc === packageNDC : ndc.startsWith(productNDC)
        ) || [];
    
        return {
          // Basic drug information
          brand_name: drug.openfda.brand_name || [],
          generic_name: drug.openfda.generic_name || [],
          manufacturer_name: drug.openfda.manufacturer_name || [],
          product_type: drug.openfda.product_type || [],
          route: drug.openfda.route || [],
          substance_name: drug.openfda.substance_name || [],
          
          // NDC information
          matching_product_ndc: matchingProductNDCs,
          matching_package_ndc: matchingPackageNDCs,
          all_product_ndc: drug.openfda.product_ndc || [],
          all_package_ndc: drug.openfda.package_ndc || [],
          
          // Additional product details
          dosage_and_administration: drug.dosage_and_administration || [],
          package_label_principal_display_panel: drug.package_label_principal_display_panel || [],
          active_ingredient: drug.active_ingredient || [],
          purpose: drug.purpose || []
        };
      });
    
      // Summary information
      const totalPackages = results.reduce((sum, result) => 
        sum + result.matching_package_ndc.length, 0
      );
    
      const searchSummary = packageNDC 
        ? `Searched for specific package NDC: ${packageNDC}`
        : `Searched for product NDC: ${productNDC} (all packages)`;
    
      return {
        content: [{
          type: "text",
          text: `✅ Found ${results.length} drug(s) with ${totalPackages} package(s) for NDC "${ndcCode}"\n\n${searchSummary}\n\n${JSON.stringify(results, null, 2)}`,
        }],
      };
    }
  • Zod input schema defining the 'ndcCode' parameter for the tool.
    {
      ndcCode: z.string().describe("National Drug Code (NDC) - accepts formats: XXXXX-XXXX, XXXXX-XXXX-XX, or without dashes")
    },
  • src/index.ts:371-474 (registration)
    Registration of the 'get-drug-by-ndc' tool with McpServer using server.tool(), including name, description, input schema, and inline handler function.
    server.tool(
      "get-drug-by-ndc",
      "Get drug information by National Drug Code (NDC). Accepts both product NDC (XXXXX-XXXX) and package NDC (XXXXX-XXXX-XX) formats. Also accepts NDC codes without dashes.",
      {
        ndcCode: z.string().describe("National Drug Code (NDC) - accepts formats: XXXXX-XXXX, XXXXX-XXXX-XX, or without dashes")
      },
      async ({ ndcCode }) => {
        const { productNDC, packageNDC, isValid } = normalizeNDC(ndcCode);
        
        if (!isValid) {
          return {
            content: [{
              type: "text",
              text: `Invalid NDC format: "${ndcCode}"\n\n✅ Accepted formats:\n• Product NDC: 12345-1234\n• Package NDC: 12345-1234-01\n• Without dashes: 123451234 or 12345123401`,
            }],
          };
        }
    
        console.log(`Searching for NDC: input="${ndcCode}", productNDC="${productNDC}", packageNDC="${packageNDC}"`);
    
        // Try searching by product NDC first (most flexible)
        let searchQuery = `openfda.product_ndc:"${productNDC}"`;
        
        // If a specific package was requested, also search package NDC
        if (packageNDC) {
          searchQuery += `+OR+openfda.package_ndc:"${packageNDC}"`;
        }
    
        const url = new OpenFDABuilder()
          .context("label")
          .search(searchQuery)
          .limit(10) // Get multiple results since product NDC might have multiple packages
          .build();
    
        const { data: drugData, error } = await makeOpenFDARequest<OpenFDAResponse>(url);
        
        if (error) {
          return {
            content: [{
              type: "text",
              text: `Failed to retrieve drug data for NDC "${ndcCode}": ${error.message}`,
            }],
          };
        }
    
        if (!drugData || !drugData.results || drugData.results.length === 0) {
          return {
            content: [{
              type: "text",
              text: `No drug found with NDC "${ndcCode}" (product: ${productNDC}).\n\n💡 Tips:\n• Verify the NDC format\n• Try without the package suffix (e.g., use 12345-1234 instead of 12345-1234-01)\n• Check if this is an FDA-approved product`,
            }],
          };
        }
    
        // Process results and group by product
        const results = drugData.results.map(drug => {
          const matchingProductNDCs = drug.openfda.product_ndc?.filter(ndc => 
            ndc === productNDC
          ) || [];
          
          const matchingPackageNDCs = drug.openfda.package_ndc?.filter(ndc => 
            packageNDC ? ndc === packageNDC : ndc.startsWith(productNDC)
          ) || [];
    
          return {
            // Basic drug information
            brand_name: drug.openfda.brand_name || [],
            generic_name: drug.openfda.generic_name || [],
            manufacturer_name: drug.openfda.manufacturer_name || [],
            product_type: drug.openfda.product_type || [],
            route: drug.openfda.route || [],
            substance_name: drug.openfda.substance_name || [],
            
            // NDC information
            matching_product_ndc: matchingProductNDCs,
            matching_package_ndc: matchingPackageNDCs,
            all_product_ndc: drug.openfda.product_ndc || [],
            all_package_ndc: drug.openfda.package_ndc || [],
            
            // Additional product details
            dosage_and_administration: drug.dosage_and_administration || [],
            package_label_principal_display_panel: drug.package_label_principal_display_panel || [],
            active_ingredient: drug.active_ingredient || [],
            purpose: drug.purpose || []
          };
        });
    
        // Summary information
        const totalPackages = results.reduce((sum, result) => 
          sum + result.matching_package_ndc.length, 0
        );
    
        const searchSummary = packageNDC 
          ? `Searched for specific package NDC: ${packageNDC}`
          : `Searched for product NDC: ${productNDC} (all packages)`;
    
        return {
          content: [{
            type: "text",
            text: `✅ Found ${results.length} drug(s) with ${totalPackages} package(s) for NDC "${ndcCode}"\n\n${searchSummary}\n\n${JSON.stringify(results, null, 2)}`,
          }],
        };
      }
    );
  • Helper function to normalize various NDC input formats (with/without dashes, product/package) into standardized productNDC and optional packageNDC, with format validation. Used by the get-drug-by-ndc handler.
    // Helper function to normalize and validate NDC format
    function normalizeNDC(ndc: string): { productNDC: string; packageNDC: string | null; isValid: boolean } {
      // Remove spaces and convert to uppercase
      const cleanNDC = ndc.trim().toUpperCase();
      
      // Check for different NDC formats:
      // 1. XXXXX-XXXX (product NDC)
      // 2. XXXXX-XXXX-XX (package NDC) 
      // 3. XXXXXXXXXXX (11-digit without dashes)
      // 4. XXXXXXXXX (9-digit without dashes - product only)
      
      let productNDC: string;
      let packageNDC: string | null = null;
      
      if (cleanNDC.includes('-')) {
        const parts = cleanNDC.split('-');
        
        if (parts.length === 2) {
          // Format: XXXXX-XXXX (product NDC)
          productNDC = cleanNDC;
          packageNDC = null;
        } else if (parts.length === 3) {
          // Format: XXXXX-XXXX-XX (package NDC)
          productNDC = `${parts[0]}-${parts[1]}`;
          packageNDC = cleanNDC;
        } else {
          return { productNDC: cleanNDC, packageNDC: null, isValid: false };
        }
      } else {
        // No dashes - need to format based on length
        if (cleanNDC.length === 11) {
          // 11-digit package NDC: XXXXXYYYYZZ -> XXXXX-YYYY-ZZ
          productNDC = `${cleanNDC.substring(0, 5)}-${cleanNDC.substring(5, 9)}`;
          packageNDC = `${cleanNDC.substring(0, 5)}-${cleanNDC.substring(5, 9)}-${cleanNDC.substring(9, 11)}`;
        } else if (cleanNDC.length === 9) {
          // 9-digit product NDC: XXXXXXXXX -> XXXXX-XXXX
          productNDC = `${cleanNDC.substring(0, 5)}-${cleanNDC.substring(5, 9)}`;
          packageNDC = null;
        } else {
          return { productNDC: cleanNDC, packageNDC: null, isValid: false };
        }
      }
      
      // Basic validation
      const isValid = /^\d{5}-\d{4}$/.test(productNDC);
      
      return { productNDC, packageNDC, isValid };
    }

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/ythalorossy/openfda'

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