Skip to main content
Glama

get_eqtl_genes

Identify genes with expression quantitative trait loci (eQTL) associations for a specific genomic region using GTEx data. Optionally filter results by tissue type to analyze gene expression regulation.

Instructions

Get genes with eQTL associations for a genomic region

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
chrYesChromosome (e.g., chr1, chr2, chrX)
startYesStart position (1-based)
endYesEnd position (1-based)
tissueSiteDetailIdNoTissue site detail ID (optional, for tissue-specific results)
datasetIdNoGTEx dataset ID (default: gtex_v8)gtex_v8

Implementation Reference

  • The main handler function for the 'get_eqtl_genes' tool. It calls the API client to fetch eQTL genes, handles errors, groups results by tissue, sorts by significance, formats a detailed markdown output with top genes, statistics, and summaries per tissue.
    async getEQTLGenes(args: any) {
      const result = await this.apiClient.getEQTLGenes({
        tissueSiteDetailId: args.tissueIds,
        datasetId: args.datasetId || 'gtex_v8',
        page: args.page || 0,
        itemsPerPage: args.itemsPerPage || 250
      });
    
      if (result.error) {
        return {
          content: [{
            type: "text",
            text: `Error retrieving eQTL genes: ${result.error}`
          }],
          isError: true
        };
      }
    
      const eqtlGenes = result.data || [];
      if (eqtlGenes.length === 0) {
        return {
          content: [{
            type: "text",
            text: `No eQTL genes found${args.tissueIds ? ` for tissues: ${args.tissueIds.join(', ')}` : ''}`
          }]
        };
      }
    
      // Group by tissue for better organization
      const tissueGroups: { [key: string]: any[] } = {};
      eqtlGenes.forEach(gene => {
        if (!tissueGroups[gene.tissueSiteDetailId]) {
          tissueGroups[gene.tissueSiteDetailId] = [];
        }
        tissueGroups[gene.tissueSiteDetailId].push(gene);
      });
    
      let output = `**eQTL Genes (${eqtlGenes.length} results)**\n`;
      output += `Dataset: ${eqtlGenes[0]?.datasetId}\n`;
      output += `Tissues: ${Object.keys(tissueGroups).length}\n\n`;
    
      Object.entries(tissueGroups).forEach(([tissueId, genes]) => {
        const tissueDisplayName = this.getTissueDisplayName(tissueId);
        output += `### ${tissueDisplayName} (${genes.length} eGenes)\n`;
    
        // Sort by significance (lowest q-value first)
        const sortedGenes = genes.sort((a, b) => a.qValue - b.qValue);
        
        // Show top significant genes
        const topCount = Math.min(10, sortedGenes.length);
        sortedGenes.slice(0, topCount).forEach((gene, index) => {
          output += `${(index + 1).toString().padStart(2)}. **${gene.geneSymbol}** (${gene.gencodeId})\n`;
          output += `    • p-value: ${gene.pValue.toExponential(2)}\n`;
          output += `    • q-value: ${gene.qValue.toFixed(4)}\n`;
          output += `    • Empirical p-value: ${gene.empiricalPValue.toExponential(2)}\n`;
          output += `    • Log2 allelic fold change: ${gene.log2AllelicFoldChange.toFixed(3)}\n`;
          output += `    • p-value threshold: ${gene.pValueThreshold.toExponential(2)}\n`;
        });
    
        if (sortedGenes.length > topCount) {
          output += `    ... and ${sortedGenes.length - topCount} more eGenes\n`;
        }
    
        // Statistics for this tissue
        const qValues = sortedGenes.map(g => g.qValue);
        const foldChanges = sortedGenes.map(g => Math.abs(g.log2AllelicFoldChange));
        
        output += `\n**Tissue Summary:**\n`;
        output += `  • Total eGenes: ${genes.length}\n`;
        output += `  • Most significant q-value: ${Math.min(...qValues).toExponential(2)}\n`;
        output += `  • Mean |fold change|: ${(foldChanges.reduce((sum, fc) => sum + fc, 0) / foldChanges.length).toFixed(3)}\n`;
        output += `  • Max |fold change|: ${Math.max(...foldChanges).toFixed(3)}\n\n`;
      });
    
      if (result.paging_info && result.paging_info.totalNumberOfItems > eqtlGenes.length) {
        output += `**Note:** Showing ${eqtlGenes.length} of ${result.paging_info.totalNumberOfItems} total results.\n`;
      }
    
      return {
        content: [{
          type: "text",
          text: output.trim()
        }]
      };
    }
  • src/index.ts:219-247 (registration)
    Tool registration in the ListToolsRequestSchema handler, defining the tool name, description, and input schema.
    name: "get_eqtl_genes",
    description: "Get genes with eQTL associations for a genomic region",
    inputSchema: {
      type: "object",
      properties: {
        chr: {
          type: "string",
          description: "Chromosome (e.g., chr1, chr2, chrX)"
        },
        start: {
          type: "integer",
          description: "Start position (1-based)"
        },
        end: {
          type: "integer", 
          description: "End position (1-based)"
        },
        tissueSiteDetailId: {
          type: "string",
          description: "Tissue site detail ID (optional, for tissue-specific results)"
        },
        datasetId: {
          type: "string",
          description: "GTEx dataset ID (default: gtex_v8)",
          default: "gtex_v8"
        }
      },
      required: ["chr", "start", "end"]
    }
  • src/index.ts:672-676 (registration)
    Dispatch registration in the CallToolRequestSchema handler, mapping tool calls to the associationHandlers.getEQTLGenes method.
    if (name === "get_eqtl_genes") {
      return await associationHandlers.getEQTLGenes({
        tissueIds: args?.tissueSiteDetailId ? [args.tissueSiteDetailId] : undefined,
        datasetId: args?.datasetId
      });
  • TypeScript interface defining the input parameters for the getEQTLGenes API call, used by the API client and handler.
    export interface GetEQTLGenesParams {
      tissueSiteDetailId?: string[];
      datasetId?: string;
      page?: number;
      itemsPerPage?: number;
    }
  • API client helper method that makes the HTTP request to GTEx Portal API for eQTL genes data, used by the main handler.
    async getEQTLGenes(params: GetEQTLGenesParams): Promise<GTExApiResponse<EQTLGene[]>> {
      try {
        const queryParams = this.buildQueryParams({
          tissueSiteDetailId: params.tissueSiteDetailId,
          datasetId: params.datasetId || 'gtex_v8',
          page: params.page || 0,
          itemsPerPage: params.itemsPerPage || 250
        });
        const response = await this.axiosInstance.get(`/association/egene?${queryParams}`);
        return { 
          data: response.data.data,
          paging_info: response.data.paging_info
        };
      } catch (error) {
        return error as GTExApiResponse<EQTLGene[]>;
      }
    }
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It mentions retrieving genes with eQTL associations but doesn't cover critical aspects like data source (GTEx implied by schema but not stated), rate limits, authentication needs, or output format (e.g., list of genes, error handling). For a tool with no annotations, this is a significant gap, warranting a score of 2.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, efficient sentence: 'Get genes with eQTL associations for a genomic region.' It is front-loaded with the core purpose, has zero waste, and is appropriately sized for the tool's complexity. Every word earns its place, making it highly concise and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (retrieving eQTL-associated genes with genomic coordinates) and lack of annotations and output schema, the description is incomplete. It doesn't explain what the output includes (e.g., gene names, eQTL details), data sources, or potential limitations. For a tool with 5 parameters and no structured output info, more context is needed, resulting in a score of 2.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 100% description coverage, providing clear details for all parameters (e.g., 'chr' as chromosome, 'start' as 1-based position). The description adds no additional parameter semantics beyond what's in the schema, such as explaining interactions between parameters or usage examples. With high schema coverage, the baseline score is 3, as the description doesn't compensate but doesn't need to heavily.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose: 'Get genes with eQTL associations for a genomic region.' It specifies the verb ('Get'), resource ('genes with eQTL associations'), and scope ('for a genomic region'), making it easy to understand. However, it doesn't explicitly differentiate from siblings like 'get_single_tissue_eqtls' or 'get_multi_tissue_eqtls,' which limits its score to 4.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. With siblings like 'get_single_tissue_eqtls' and 'get_multi_tissue_eqtls' available, it fails to specify scenarios or exclusions, such as whether this tool is for general eQTL gene retrieval or if it's preferred over others for specific use cases. This lack of context results in a score of 2.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

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