Skip to main content
Glama

get_single_tissue_eqtls

Retrieve expression quantitative trait loci (eQTL) results for a specific gene in a particular human tissue from the GTEx dataset to analyze genetic regulation of gene expression.

Instructions

Get single-tissue eQTL results for a gene

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
gencodeIdYesGENCODE gene ID (e.g., ENSG00000223972.5)
tissueSiteDetailIdYesTissue site detail ID (e.g., Muscle_Skeletal, Brain_Cortex)
datasetIdNoGTEx dataset ID (default: gtex_v8)gtex_v8

Implementation Reference

  • Main handler function that executes the tool logic: validates args, calls API client, formats and groups eQTL results by tissue/gene, generates formatted text output.
    async getSingleTissueEQTLs(args: any) {
      if (!args.geneIds && !args.variantIds && !args.tissueIds) {
        throw new Error('At least one of geneIds, variantIds, or tissueIds must be provided');
      }
    
      const result = await this.apiClient.getSingleTissueEQTLs({
        gencodeId: args.geneIds,
        variantId: args.variantIds,
        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 single tissue eQTLs: ${result.error}`
          }],
          isError: true
        };
      }
    
      const eqtls = result.data || [];
      if (eqtls.length === 0) {
        return {
          content: [{
            type: "text",
            text: "No significant single tissue eQTLs found for the specified parameters."
          }]
        };
      }
    
      let output = `**Single Tissue eQTLs (${eqtls.length} results)**\n`;
      output += `Dataset: ${eqtls[0]?.datasetId}\n\n`;
    
      // Group by gene or tissue depending on query
      if (args.geneIds && args.geneIds.length === 1) {
        // Single gene query - group by tissue
        const tissueGroups: { [key: string]: any[] } = {};
        eqtls.forEach(eqtl => {
          if (!tissueGroups[eqtl.tissueSiteDetailId]) {
            tissueGroups[eqtl.tissueSiteDetailId] = [];
          }
          tissueGroups[eqtl.tissueSiteDetailId].push(eqtl);
        });
    
        const geneName = eqtls[0]?.geneSymbol;
        output += `**Gene:** ${geneName} (${eqtls[0]?.gencodeId})\n\n`;
    
        Object.entries(tissueGroups).forEach(([tissueId, tissueEqtls]) => {
          const tissueDisplayName = this.getTissueDisplayName(tissueId);
          output += `### ${tissueDisplayName} (${tissueEqtls.length} eQTLs)\n`;
    
          // Sort by significance
          const sortedEqtls = tissueEqtls.sort((a, b) => a.pValue - b.pValue);
          const topEqtls = sortedEqtls.slice(0, 5);
    
          topEqtls.forEach((eqtl, index) => {
            output += `${index + 1}. **${eqtl.snpId}** (${eqtl.variantId})\n`;
            output += `   • Position: ${eqtl.chromosome}:${eqtl.pos.toLocaleString()}\n`;
            output += `   • p-value: ${eqtl.pValue.toExponential(2)}\n`;
            output += `   • NES: ${eqtl.nes.toFixed(3)}\n`;
          });
    
          if (sortedEqtls.length > 5) {
            output += `   ... and ${sortedEqtls.length - 5} more eQTLs\n`;
          }
          output += '\n';
        });
    
      } else {
        // Multiple genes or other query types - group by gene
        const geneGroups: { [key: string]: any[] } = {};
        eqtls.forEach(eqtl => {
          const key = `${eqtl.geneSymbol} (${eqtl.gencodeId})`;
          if (!geneGroups[key]) {
            geneGroups[key] = [];
          }
          geneGroups[key].push(eqtl);
        });
    
        Object.entries(geneGroups).forEach(([geneKey, geneEqtls]) => {
          output += `### ${geneKey}\n`;
    
          // Group by tissue within gene
          const tissueGroups: { [key: string]: any[] } = {};
          geneEqtls.forEach(eqtl => {
            if (!tissueGroups[eqtl.tissueSiteDetailId]) {
              tissueGroups[eqtl.tissueSiteDetailId] = [];
            }
            tissueGroups[eqtl.tissueSiteDetailId].push(eqtl);
          });
    
          // Show most significant eQTL per tissue
          Object.entries(tissueGroups).forEach(([tissueId, tissueEqtls]) => {
            const tissueDisplayName = this.getTissueDisplayName(tissueId);
            const bestEqtl = tissueEqtls.sort((a, b) => a.pValue - b.pValue)[0];
            
            output += `  **${tissueDisplayName}**: ${bestEqtl.snpId} (p=${bestEqtl.pValue.toExponential(2)}, NES=${bestEqtl.nes.toFixed(3)})`;
            if (tissueEqtls.length > 1) {
              output += ` + ${tissueEqtls.length - 1} more`;
            }
            output += '\n';
          });
          output += '\n';
        });
      }
    
      if (result.paging_info && result.paging_info.totalNumberOfItems > eqtls.length) {
        output += `**Note:** Showing ${eqtls.length} of ${result.paging_info.totalNumberOfItems} total results.\n`;
      }
    
      return {
        content: [{
          type: "text",
          text: output.trim()
        }]
      };
    }
  • src/index.ts:678-683 (registration)
    Tool dispatch/registration in the main CallToolRequestHandler: maps tool name to AssociationHandlers.getSingleTissueEQTLs call with parameter adaptation.
    if (name === "get_single_tissue_eqtls") {
      return await associationHandlers.getSingleTissueEQTLs({
        geneIds: args?.gencodeId ? [args.gencodeId] : undefined,
        tissueIds: args?.tissueSiteDetailId ? [args.tissueSiteDetailId] : undefined,
        datasetId: args?.datasetId
      });
  • Tool schema registration including inputSchema definition for parameters (gencodeId, tissueSiteDetailId, datasetId).
    name: "get_single_tissue_eqtls", 
    description: "Get single-tissue eQTL results for a gene",
    inputSchema: {
      type: "object",
      properties: {
        gencodeId: {
          type: "string",
          description: "GENCODE gene ID (e.g., ENSG00000223972.5)"
        },
        tissueSiteDetailId: {
          type: "string",
          description: "Tissue site detail ID (e.g., Muscle_Skeletal, Brain_Cortex)"
        },
        datasetId: {
          type: "string",
          description: "GTEx dataset ID (default: gtex_v8)",
          default: "gtex_v8"
        }
      },
      required: ["gencodeId", "tissueSiteDetailId"]
    }
  • TypeScript interface defining parameters for the getSingleTissueEQTLs API call.
    export interface GetSingleTissueEQTLsParams {
      gencodeId?: string[];
      variantId?: string[];
      tissueSiteDetailId?: string[];
      datasetId?: string;
      page?: number;
      itemsPerPage?: number;
    }
  • API client helper method that performs the HTTP request to GTEx Portal API for single tissue eQTLs.
    async getSingleTissueEQTLs(params: GetSingleTissueEQTLsParams): Promise<GTExApiResponse<SingleTissueEQTL[]>> {
      try {
        const queryParams = this.buildQueryParams({
          gencodeId: params.gencodeId,
          variantId: params.variantId,
          tissueSiteDetailId: params.tissueSiteDetailId,
          datasetId: params.datasetId || 'gtex_v8',
          page: params.page || 0,
          itemsPerPage: params.itemsPerPage || 250
        });
        const response = await this.axiosInstance.get(`/association/singleTissueEqtl?${queryParams}`);
        return { 
          data: response.data.data,
          paging_info: response.data.paging_info
        };
      } catch (error) {
        return error as GTExApiResponse<SingleTissueEQTL[]>;
      }

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