Skip to main content
Glama

get-drug-safety-info

Retrieve comprehensive drug safety information including warnings, contraindications, drug interactions, and precautions from the OpenFDA database using brand names.

Instructions

Get comprehensive safety information for a drug including warnings, contraindications, drug interactions, and precautions. Use brand name.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
drugNameYesDrug brand name

Implementation Reference

  • The handler function fetches drug labeling data from OpenFDA API using the provided brand name, extracts safety-related fields (warnings, contraindications, interactions, etc.), and returns formatted JSON safety information.
    async ({ drugName }) => { const url = new OpenFDABuilder() .context("label") .search(`openfda.brand_name:"${drugName}"`) .limit(1) .build(); const { data: drugData, error } = await makeOpenFDARequest<OpenFDAResponse>(url); if (error) { return { content: [{ type: "text", text: `Failed to retrieve safety information for "${drugName}": ${error.message}`, }], }; } if (!drugData || !drugData.results || drugData.results.length === 0) { return { content: [{ type: "text", text: `No safety information found for "${drugName}".`, }], }; } const drug = drugData.results[0]; const safetyInfo = { drug_name: drug?.openfda.brand_name?.[0] || drugName, generic_name: drug?.openfda.generic_name?.[0] || 'Unknown', warnings: drug?.warnings || [], contraindications: drug?.contraindications || [], drug_interactions: drug?.drug_interactions || [], precautions: drug?.precautions || [], adverse_reactions: drug?.adverse_reactions || [], overdosage: drug?.overdosage || [], do_not_use: drug?.do_not_use || [], ask_doctor: drug?.ask_doctor || [], stop_use: drug?.stop_use || [], pregnancy_or_breast_feeding: drug?.pregnancy_or_breast_feeding || [] }; return { content: [{ type: "text", text: `Safety information for "${drugName}":\n\n${JSON.stringify(safetyInfo, null, 2)}`, }], }; }
  • Input schema defined with Zod: requires 'drugName' as string.
    { drugName: z.string().describe("Drug brand name") },
  • src/index.ts:313-369 (registration)
    Registration of the 'get-drug-safety-info' tool using server.tool() with name, description, input schema, and handler reference.
    server.tool( "get-drug-safety-info", "Get comprehensive safety information for a drug including warnings, contraindications, drug interactions, and precautions. Use brand name.", { drugName: z.string().describe("Drug brand name") }, async ({ drugName }) => { const url = new OpenFDABuilder() .context("label") .search(`openfda.brand_name:"${drugName}"`) .limit(1) .build(); const { data: drugData, error } = await makeOpenFDARequest<OpenFDAResponse>(url); if (error) { return { content: [{ type: "text", text: `Failed to retrieve safety information for "${drugName}": ${error.message}`, }], }; } if (!drugData || !drugData.results || drugData.results.length === 0) { return { content: [{ type: "text", text: `No safety information found for "${drugName}".`, }], }; } const drug = drugData.results[0]; const safetyInfo = { drug_name: drug?.openfda.brand_name?.[0] || drugName, generic_name: drug?.openfda.generic_name?.[0] || 'Unknown', warnings: drug?.warnings || [], contraindications: drug?.contraindications || [], drug_interactions: drug?.drug_interactions || [], precautions: drug?.precautions || [], adverse_reactions: drug?.adverse_reactions || [], overdosage: drug?.overdosage || [], do_not_use: drug?.do_not_use || [], ask_doctor: drug?.ask_doctor || [], stop_use: drug?.stop_use || [], pregnancy_or_breast_feeding: drug?.pregnancy_or_breast_feeding || [] }; return { content: [{ type: "text", text: `Safety information for "${drugName}":\n\n${JSON.stringify(safetyInfo, null, 2)}`, }], }; } );
  • OpenFDABuilder class constructs the OpenFDA API URL with context='label', search by brand_name, and limit=1, as used in the handler.
    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 function performs robust HTTP request to OpenFDA API with retry logic, timeout handling, and detailed error types, used to fetch the drug data.
    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