Skip to main content
Glama

get-drugs-by-manufacturer

Find drugs produced by a specific pharmaceutical company. Use this tool to identify manufacturer portfolios or locate alternative medications from the same source.

Instructions

Get all drugs manufactured by a specific company. Useful for finding alternatives or checking manufacturer portfolios.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
manufacturerNameYesManufacturer/company name
limitNoMaximum number of drugs to return

Implementation Reference

  • The handler function for the 'get-drugs-by-manufacturer' tool. It constructs an OpenFDA API query for drugs by manufacturer name, fetches the data, handles errors and empty results, maps the response to a simplified list of drugs (brand_name, generic_name, product_type, route, ndc), and returns formatted text content.
    async ({ manufacturerName, limit }) => {
      const url = new OpenFDABuilder()
        .context("label")
        .search(`openfda.manufacturer_name:"${manufacturerName}"`)
        .limit(limit)
        .build();
    
      const { data: drugData, error } = await makeOpenFDARequest<OpenFDAResponse>(url);
      
      if (error) {
        return {
          content: [{
            type: "text",
            text: `Failed to retrieve drugs for manufacturer "${manufacturerName}": ${error.message}`,
          }],
        };
      }
    
      if (!drugData || !drugData.results || drugData.results.length === 0) {
        return {
          content: [{
            type: "text",
            text: `No drugs found for manufacturer "${manufacturerName}".`,
          }],
        };
      }
    
      const drugs = drugData.results.map(drug => ({
        brand_name: drug?.openfda.brand_name?.[0] || 'Unknown',
        generic_name: drug?.openfda.generic_name?.[0] || 'Unknown',
        product_type: drug?.openfda.product_type?.[0] || 'Unknown',
        route: drug?.openfda.route || [],
        ndc: drug?.openfda.product_ndc?.[0] || 'Unknown'
      }));
    
      return {
        content: [{
          type: "text",
          text: `Found ${drugs.length} drug(s) from manufacturer "${manufacturerName}":\n\n${JSON.stringify(drugs, null, 2)}`,
        }],
      };
    }
  • Zod input schema for the tool defining parameters: manufacturerName (required string) and limit (optional number, default 20).
      manufacturerName: z.string().describe("Manufacturer/company name"),
      limit: z.number().optional().default(20).describe("Maximum number of drugs to return")
    },
  • src/index.ts:262-311 (registration)
    Registration of the 'get-drugs-by-manufacturer' tool using McpServer.tool() method, including name, description, schema, and handler function.
    server.tool(
      "get-drugs-by-manufacturer",
      "Get all drugs manufactured by a specific company. Useful for finding alternatives or checking manufacturer portfolios.",
      {
        manufacturerName: z.string().describe("Manufacturer/company name"),
        limit: z.number().optional().default(20).describe("Maximum number of drugs to return")
      },
      async ({ manufacturerName, limit }) => {
        const url = new OpenFDABuilder()
          .context("label")
          .search(`openfda.manufacturer_name:"${manufacturerName}"`)
          .limit(limit)
          .build();
    
        const { data: drugData, error } = await makeOpenFDARequest<OpenFDAResponse>(url);
        
        if (error) {
          return {
            content: [{
              type: "text",
              text: `Failed to retrieve drugs for manufacturer "${manufacturerName}": ${error.message}`,
            }],
          };
        }
    
        if (!drugData || !drugData.results || drugData.results.length === 0) {
          return {
            content: [{
              type: "text",
              text: `No drugs found for manufacturer "${manufacturerName}".`,
            }],
          };
        }
    
        const drugs = drugData.results.map(drug => ({
          brand_name: drug?.openfda.brand_name?.[0] || 'Unknown',
          generic_name: drug?.openfda.generic_name?.[0] || 'Unknown',
          product_type: drug?.openfda.product_type?.[0] || 'Unknown',
          route: drug?.openfda.route || [],
          ndc: drug?.openfda.product_ndc?.[0] || 'Unknown'
        }));
    
        return {
          content: [{
            type: "text",
            text: `Found ${drugs.length} drug(s) from manufacturer "${manufacturerName}":\n\n${JSON.stringify(drugs, null, 2)}`,
          }],
        };
      }
    );
  • OpenFDABuilder class used in the handler to construct the OpenFDA API URL with context='label', search='openfda.manufacturer_name:"{name}"', and limit.
    export class OpenFDABuilder {
      private url = "https://api.fda.gov/drug/";
      private params = new Map<string, string | number>();
    
      context(context: ContextType): this {
        this.params.set("context", context);
        return this;
      }
    
      search(query: string): this {
        this.params.set("search", query);
        return this;
      }
    
      limit(max: number = 1): this {
        this.params.set("limit", max);
        return this;
      }
    
      build(): string {
        const context = this.params.get("context");
        const search = this.params.get("search");
        const limit = this.params.get("limit");
        const apiKey = process.env.OPENFDA_API_KEY;
    
        if (!context || !search || !limit) {
          throw new Error("Missing required parameters: context, search, or limit");
        }
    
        return `${this.url}${context}.json?api_key=${apiKey}&search=${search}&limit=${limit}`;
      }
    }
  • makeOpenFDARequest utility function called in the handler to perform the resilient HTTP fetch to the constructed OpenFDA URL, with comprehensive error handling and retries.
    async function makeOpenFDARequest<T>(
      url: string,
      config: RequestConfig = {}
    ): Promise<{ data: T | null; error: OpenFDAError | null }> {
      const { maxRetries, retryDelay, timeout } = { ...DEFAULT_CONFIG, ...config };
    
      const headers = {
        "User-Agent": "@ythalorossy/openfda",
        Accept: "application/json",
      };
    
      let lastError: OpenFDAError | null = null;
    
      for (let attempt = 0; attempt <= maxRetries!; attempt++) {
        try {
          // Create abort controller for timeout handling
          const controller = new AbortController();
          const timeoutId = setTimeout(() => controller.abort(), timeout);
    
          console.log(
            `Making OpenFDA request (attempt ${attempt + 1}/${
              maxRetries! + 1
            }): ${url}`
          );
    
          const response = await fetch(url, {
            headers,
            signal: controller.signal,
          });
    
          clearTimeout(timeoutId);
    
          // Handle HTTP errors with OpenFDA-specific context
          if (!response.ok) {
            const errorText = await response
              .text()
              .catch(() => "Unable to read error response");
    
            const httpError: OpenFDAError = {
              type: "http",
              message: `HTTP ${response.status}: ${response.statusText}`,
              status: response.status,
              details: errorText,
            };
    
            console.error(`OpenFDA HTTP Error (${response.status}):`, {
              url,
              status: response.status,
              statusText: response.statusText,
              errorText: errorText.substring(0, 200), // Truncate long error messages
            });
    
            // OpenFDA-specific status code handling
            switch (response.status) {
              case 400:
                httpError.message = `Bad Request: Invalid search query or parameters`;
                break;
              case 401:
                httpError.message = `Unauthorized: Invalid or missing API key`;
                break;
              case 403:
                httpError.message = `Forbidden: API key may be invalid or quota exceeded`;
                break;
              case 404:
                httpError.message = `Not Found: No results found for the specified query`;
                break;
              case 429:
                httpError.message = `Rate Limited: Too many requests. Retrying...`;
                break;
              case 500:
                httpError.message = `Server Error: OpenFDA service is experiencing issues`;
                break;
              default:
                httpError.message = `HTTP Error ${response.status}: ${response.statusText}`;
            }
    
            lastError = httpError;
    
            // Don't retry client errors (4xx) except rate limiting
            if (
              response.status >= 400 &&
              response.status < 500 &&
              response.status !== 429
            ) {
              break;
            }
    
            // Retry server errors and rate limits
            if (
              attempt < maxRetries! &&
              isRetryableError({ status: response.status })
            ) {
              const delay = retryDelay! * Math.pow(2, attempt); // Exponential backoff
              console.log(`Retrying in ${delay}ms...`);
              await sleep(delay);
              continue;
            }
    
            break;
          }
    
          // Parse JSON response
          let parsedData: any;
          try {
            parsedData = await response.json();
          } catch (parseError) {
            const parsingError: OpenFDAError = {
              type: "parsing",
              message: `Failed to parse JSON response: ${
                parseError instanceof Error
                  ? parseError.message
                  : "Unknown parsing error"
              }`,
              details: parseError,
            };
    
            console.error("OpenFDA JSON Parsing Error:", {
              url,
              parseError:
                parseError instanceof Error ? parseError.message : parseError,
            });
    
            lastError = parsingError;
            break; // Don't retry parsing errors
          }
    
          // Check for empty response
          if (!parsedData) {
            const emptyError: OpenFDAError = {
              type: "empty_response",
              message: "Received empty response from OpenFDA API",
            };
            lastError = emptyError;
            break;
          }
    
          console.log(`OpenFDA request successful on attempt ${attempt + 1}`);
          return { data: parsedData as T, error: null };
        } catch (error: any) {
          // Handle network errors, timeouts, and other fetch errors
          let networkError: OpenFDAError;
    
          if (error.name === "AbortError") {
            networkError = {
              type: "timeout",
              message: `Request timeout after ${timeout}ms`,
              details: error,
            };
          } else if (
            error instanceof TypeError &&
            error.message.includes("fetch")
          ) {
            networkError = {
              type: "network",
              message: `Network error: Unable to connect to OpenFDA API`,
              details: error.message,
            };
          } else {
            networkError = {
              type: "unknown",
              message: `Unexpected error: ${
                error.message || "Unknown error occurred"
              }`,
              details: error,
            };
          }
    
          console.error(`OpenFDA Request Error (attempt ${attempt + 1}):`, {
            url,
            error: error.message,
            type: error.name,
          });
    
          lastError = networkError;
    
          // Retry network errors and timeouts
          if (attempt < maxRetries! && isRetryableError(error)) {
            const delay = retryDelay! * Math.pow(2, attempt); // Exponential backoff
            console.log(`Network error, retrying in ${delay}ms...`);
            await sleep(delay);
            continue;
          }
    
          break;
        }
      }
    
      return { data: null, error: lastError };
    }

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