Skip to main content
Glama
pubchem.ts9.97 kB
import { z } from "zod"; import { BaseTool } from "./base.js"; export class PubChemCompoundTool extends BaseTool { register(): void { this.context.server.tool( "pubchem_compound", "Get detailed compound information from PubChem including chemical properties, synonyms, and classifications. Search by CID, name, SMILES, InChI, or molecular formula.", { identifier_type: z .enum(["cid", "name", "smiles", "inchi", "inchikey", "formula"]) .describe("Type of identifier"), identifier: z.string().describe("Compound identifier"), operation: z .enum([ "record", "property", "synonyms", "classification", "conformers", ]) .default("record") .describe("Type of data to retrieve"), property_list: z .string() .optional() .describe( "Comma-separated list of properties (for property operation)", ), output_format: z .enum(["json", "xml", "sdf", "csv", "png", "txt"]) .default("json") .describe("Output format"), }, async ({ identifier_type, identifier, operation, property_list, output_format, }) => { try { if (!identifier || identifier.trim() === "") { throw new Error("Identifier cannot be empty"); } let url = `https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound/${identifier_type}/${encodeURIComponent(identifier.trim())}`; if (operation === "property" && property_list) { url += `/property/${property_list}`; } else if (operation !== "record") { url += `/${operation}`; } url += `/${output_format.toUpperCase()}`; // Add tool and email parameters const params = new URLSearchParams({ tool: this.context.defaultTool, email: this.context.defaultEmail, }); url += `?${params}`; const response = await fetch(url); const data = await this.parseResponse(response, "PubChem Compound"); return { content: [ { type: "text", text: `PubChem Compound Results:\n\n${this.formatResponseData(data)}`, }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error in PubChem Compound: ${error instanceof Error ? error.message : String(error)}`, }, ], }; } }, ); } } export class PubChemSubstanceTool extends BaseTool { register(): void { this.context.server.tool( "pubchem_substance", "Get substance information from PubChem including substance records, synonyms, and cross-references. Search by SID, source ID, name, or external references.", { identifier_type: z .enum(["sid", "sourceid", "name", "xref"]) .describe("Type of identifier"), identifier: z.string().describe("Substance identifier"), operation: z .enum(["record", "synonyms", "classification", "xrefs"]) .default("record") .describe("Type of data to retrieve"), output_format: z .enum(["json", "xml", "sdf", "csv", "txt"]) .default("json") .describe("Output format"), }, async ({ identifier_type, identifier, operation, output_format }) => { try { if (!identifier || identifier.trim() === "") { throw new Error("Identifier cannot be empty"); } let url = `https://pubchem.ncbi.nlm.nih.gov/rest/pug/substance/${identifier_type}/${encodeURIComponent(identifier.trim())}`; if (operation !== "record") { url += `/${operation}`; } url += `/${output_format.toUpperCase()}`; // Add tool and email parameters const params = new URLSearchParams({ tool: this.context.defaultTool, email: this.context.defaultEmail, }); url += `?${params}`; const response = await fetch(url); const data = await this.parseResponse(response, "PubChem Substance"); return { content: [ { type: "text", text: `PubChem Substance Results:\n\n${this.formatResponseData(data)}`, }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error in PubChem Substance: ${error instanceof Error ? error.message : String(error)}`, }, ], }; } }, ); } } export class PubChemBioAssayTool extends BaseTool { register(): void { this.context.server.tool( "pubchem_bioassay", "Get bioassay information from PubChem including assay descriptions, targets, and activity data. Search by AID, target, or activity type.", { identifier_type: z .enum(["aid", "listkey", "target", "activity"]) .describe("Type of identifier"), identifier: z.string().describe("BioAssay identifier"), operation: z .enum(["record", "summary", "description", "targets", "aids"]) .default("record") .describe("Type of data to retrieve"), output_format: z .enum(["json", "xml", "csv", "txt"]) .default("json") .describe("Output format"), }, async ({ identifier_type, identifier, operation, output_format }) => { try { if (!identifier || identifier.trim() === "") { throw new Error("Identifier cannot be empty"); } let url = `https://pubchem.ncbi.nlm.nih.gov/rest/pug/assay/${identifier_type}/${encodeURIComponent(identifier.trim())}`; if (operation !== "record") { url += `/${operation}`; } url += `/${output_format.toUpperCase()}`; // Add tool and email parameters const params = new URLSearchParams({ tool: this.context.defaultTool, email: this.context.defaultEmail, }); url += `?${params}`; const response = await fetch(url); const data = await this.parseResponse(response, "PubChem BioAssay"); return { content: [ { type: "text", text: `PubChem BioAssay Results:\n\n${this.formatResponseData(data)}`, }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error in PubChem BioAssay: ${error instanceof Error ? error.message : String(error)}`, }, ], }; } }, ); } } export class PubChemStructureSearchTool extends BaseTool { register(): void { this.context.server.tool( "pubchem_structure_search", "Perform structure-based searches in PubChem including identity, substructure, superstructure, and similarity searches. Input chemical structures as SMILES, InChI, SDF, or MOL.", { structure_type: z .enum(["smiles", "inchi", "sdf", "mol"]) .describe("Type of structure input"), structure: z.string().describe("Chemical structure representation"), search_type: z .enum(["identity", "substructure", "superstructure", "similarity"]) .describe("Type of structure search"), threshold: z .number() .optional() .default(90) .describe("Similarity threshold (for similarity searches, 0-100)"), max_records: z .number() .optional() .default(1000) .describe("Maximum number of records to return"), output_format: z .enum(["json", "xml", "sdf", "csv", "txt"]) .default("json") .describe("Output format"), }, async ({ structure_type, structure, search_type, threshold, max_records, output_format, }) => { try { if (!structure || structure.trim() === "") { throw new Error("Structure cannot be empty"); } // Build the correct PubChem structure search URL const baseUrl = `https://pubchem.ncbi.nlm.nih.gov/rest/pug/compound`; let url: string; const params = new URLSearchParams({ tool: this.context.defaultTool, email: this.context.defaultEmail, }); let response: Response; if (search_type === "identity") { // Identity search is synchronous and uses GET. // e.g. /compound/identity/smiles/c1ccccc1/cids/JSON url = `${baseUrl}/identity/${structure_type}/${encodeURIComponent(structure.trim())}/cids/${output_format.toUpperCase()}`; url += `?${params}`; response = await fetch(url); } else { // Other searches (substructure, superstructure, similarity) are asynchronous and use POST. // This implementation follows the PUG-REST documentation. // e.g. /compound/substructure/smiles/cids/JSON url = `${baseUrl}/${search_type}/${structure_type}/cids/${output_format.toUpperCase()}`; if (search_type === "similarity" && threshold !== undefined) { params.append("Threshold", threshold.toString()); } if (max_records !== undefined) { params.append("MaxRecords", max_records.toString()); } url += `?${params}`; response = await fetch(url, { method: "POST", headers: { "Content-Type": "text/plain" }, body: structure.trim(), }); } if (!response.ok) { const errorText = await response.text(); throw new Error( `PubChem search failed: ${response.status} ${response.statusText}. Response: ${errorText}`, ); } const responseData = await response.text(); // Check if this is a waiting response or direct results if ( responseData.includes('"Waiting"') || responseData.includes('"Running"') ) { return { content: [ { type: "text", text: `PubChem Structure Search Submitted:\n\nSearch is running. Please wait and try again with the returned key to get results.\n\n${this.formatResponseData(responseData)}`, }, ], }; } return { content: [ { type: "text", text: `PubChem Structure Search Results:\n\n${this.formatResponseData(responseData)}`, }, ], }; } catch (error) { return { content: [ { type: "text", text: `Error in PubChem Structure Search: ${error instanceof Error ? error.message : String(error)}`, }, ], }; } }, ); } }

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/QuentinCody/entrez-mcp-server'

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