Skip to main content
Glama

calculate_dynamic_eqtl

Analyze how genetic variants affect gene expression across different human tissues to identify tissue-specific regulatory effects using GTEx genomics data.

Instructions

Calculate dynamic eQTL effects across tissues

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
gencodeIdYesGENCODE gene ID (e.g., ENSG00000223972.5)
snpIdYesSNP ID (rs number or variant ID)
tissueSiteDetailIdsYesArray of tissue site detail IDs to compare
datasetIdNoGTEx dataset ID (default: gtex_v8)gtex_v8

Implementation Reference

  • Main handler function executing the tool logic: validates inputs, calls API, processes dynamic eQTL results including statistics and genotype-based expression summaries, formats rich text output.
    async calculateDynamicEQTL(args: any) { if (!args.geneId || !args.variantId || !args.tissueId) { throw new Error('geneId, variantId, and tissueId parameters are all required'); } const result = await this.apiClient.calculateDynamicEQTL({ gencodeId: args.geneId, variantId: args.variantId, tissueSiteDetailId: args.tissueId, datasetId: args.datasetId || 'gtex_v8' }); if (result.error) { return { content: [{ type: "text", text: `Error calculating dynamic eQTL: ${result.error}` }], isError: true }; } const eqtlResult = result.data; if (!eqtlResult) { return { content: [{ type: "text", text: "No dynamic eQTL result returned." }] }; } const tissueDisplayName = this.getTissueDisplayName(args.tissueId); let output = `**Dynamic eQTL Calculation**\n`; output += `Gene: **${eqtlResult.geneSymbol}** (${eqtlResult.gencodeId})\n`; output += `Variant: **${eqtlResult.variantId}**\n`; output += `Tissue: **${tissueDisplayName}**\n\n`; if (eqtlResult.error && eqtlResult.error !== 0) { output += `⚠️ **Calculation Error:** Error code ${eqtlResult.error}\n\n`; } output += `**Statistical Results:**\n`; output += `• p-value: ${eqtlResult.pValue.toExponential(2)}\n`; output += `• Normalized Effect Size (NES): ${eqtlResult.nes.toFixed(4)}\n`; output += `• t-statistic: ${eqtlResult.tStatistic.toFixed(4)}\n`; output += `• Minor Allele Frequency: ${(eqtlResult.maf * 100).toFixed(2)}%\n`; output += `• p-value threshold: ${eqtlResult.pValueThreshold.toExponential(2)}\n`; const isSignificant = eqtlResult.pValue < eqtlResult.pValueThreshold; output += `• **Significance:** ${isSignificant ? '✅ Significant' : '❌ Not significant'}\n\n`; output += `**Genotype Distribution:**\n`; output += `• Homozygous reference: ${eqtlResult.homoRefCount} samples\n`; output += `• Heterozygous: ${eqtlResult.hetCount} samples\n`; output += `• Homozygous alternate: ${eqtlResult.homoAltCount} samples\n`; const totalSamples = eqtlResult.homoRefCount + eqtlResult.hetCount + eqtlResult.homoAltCount; output += `• **Total samples:** ${totalSamples}\n\n`; if (eqtlResult.data && eqtlResult.genotypes && eqtlResult.data.length === eqtlResult.genotypes.length && eqtlResult.data.length > 0) { // Calculate expression statistics by genotype const expressionByGenotype: { [key: number]: number[] } = {}; eqtlResult.data.forEach((expr, i) => { const genotype = eqtlResult.genotypes[i]; if (!expressionByGenotype[genotype]) { expressionByGenotype[genotype] = []; } expressionByGenotype[genotype].push(expr); }); output += `**Expression by Genotype:**\n`; Object.keys(expressionByGenotype).sort().forEach(genotype => { const expressions = expressionByGenotype[parseInt(genotype)]; const mean = expressions.reduce((sum, val) => sum + val, 0) / expressions.length; const genotypeLabel = genotype === '0' ? 'Ref/Ref' : genotype === '1' ? 'Ref/Alt' : 'Alt/Alt'; output += `• ${genotypeLabel}: ${mean.toFixed(3)} TPM (${expressions.length} samples)\n`; }); } return { content: [{ type: "text", text: output }] }; }
  • src/index.ts:685-691 (registration)
    Tool registration and dispatch in the main CallToolRequest handler, mapping tool arguments to handler method call.
    if (name === "calculate_dynamic_eqtl") { return await associationHandlers.calculateDynamicEQTL({ geneId: args?.gencodeId, variantId: args?.snpId, tissueId: Array.isArray(args?.tissueSiteDetailIds) && args.tissueSiteDetailIds.length > 0 ? args.tissueSiteDetailIds[0] : undefined, datasetId: args?.datasetId });
  • Type definition for input parameters used by the API client and handler.
    export interface CalculateDynamicEQTLParams { tissueSiteDetailId: string; gencodeId: string; variantId: string; datasetId?: string; }
  • Tool input schema definition provided to MCP ListToolsRequest.
    name: "calculate_dynamic_eqtl", description: "Calculate dynamic eQTL effects across tissues", inputSchema: { type: "object", properties: { gencodeId: { type: "string", description: "GENCODE gene ID (e.g., ENSG00000223972.5)" }, snpId: { type: "string", description: "SNP ID (rs number or variant ID)" }, tissueSiteDetailIds: { type: "array", items: { type: "string" }, description: "Array of tissue site detail IDs to compare" }, datasetId: { type: "string", description: "GTEx dataset ID (default: gtex_v8)", default: "gtex_v8" } }, required: ["gencodeId", "snpId", "tissueSiteDetailIds"] }
  • API client helper method that performs the HTTP request to GTEx Portal's /association/dyneqtl endpoint.
    async calculateDynamicEQTL(params: CalculateDynamicEQTLParams): Promise<GTExApiResponse<DynamicEQTLResult>> { try { const queryParams = this.buildQueryParams({ tissueSiteDetailId: params.tissueSiteDetailId, gencodeId: params.gencodeId, variantId: params.variantId, datasetId: params.datasetId || 'gtex_v8' }); const response = await this.axiosInstance.get(`/association/dyneqtl?${queryParams}`); return { data: response.data }; } catch (error) { return error as GTExApiResponse<DynamicEQTLResult>; } }

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/Augmented-Nature/GTEx-MCP-Server'

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