Skip to main content
Glama

get_median_gene_expression

Retrieve median gene expression levels across human tissues using a GENCODE gene ID to analyze tissue-specific expression patterns from GTEx data.

Instructions

Get median gene expression levels across tissues

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
gencodeIdYesGENCODE gene ID (e.g., ENSG00000223972.5)
datasetIdNoGTEx dataset ID (default: gtex_v8)gtex_v8

Implementation Reference

  • The primary handler function for the 'get_median_gene_expression' tool. Validates inputs, fetches data from API client, groups by gene, sorts tissues by expression, computes statistics, and formats a detailed markdown response with top expressing tissues and summaries.
    async getMedianGeneExpression(args: any) {
      if (!args.geneIds || !Array.isArray(args.geneIds) || args.geneIds.length === 0) {
        throw new Error('geneIds parameter is required and must be a non-empty array of gene IDs');
      }
    
      if (args.geneIds.length > 60) {
        return {
          content: [{
            type: "text",
            text: "Maximum 60 genes can be processed at once. Please reduce the number of genes."
          }]
        };
      }
    
      const result = await this.apiClient.getMedianGeneExpression(
        args.geneIds,
        args.datasetId || 'gtex_v8',
        args.tissueIds
      );
    
      if (result.error) {
        return {
          content: [{
            type: "text",
            text: `Error retrieving median gene expression: ${result.error}`
          }],
          isError: true
        };
      }
    
      const expressions = result.data || [];
      if (expressions.length === 0) {
        return {
          content: [{
            type: "text",
            text: "No median expression data found for the specified genes."
          }]
        };
      }
    
      // Group by gene for better organization
      const geneGroups: { [key: string]: any[] } = {};
      expressions.forEach(expr => {
        const key = `${expr.geneSymbol} (${expr.gencodeId})`;
        if (!geneGroups[key]) {
          geneGroups[key] = [];
        }
        geneGroups[key].push(expr);
      });
    
      let output = `**Median Gene Expression (${expressions.length} tissue-gene combinations)**\n`;
      output += `Dataset: ${expressions[0]?.datasetId || args.datasetId}\n\n`;
    
      Object.entries(geneGroups).forEach(([geneKey, geneExpressions]) => {
        output += `### ${geneKey}\n`;
        
        // Sort by expression level (highest first)
        const sortedExpressions = geneExpressions.sort((a, b) => b.median - a.median);
        
        // Show top expressing tissues
        const topCount = Math.min(10, sortedExpressions.length);
        output += `**Top ${topCount} expressing tissues:**\n`;
        sortedExpressions.slice(0, topCount).forEach((expr, index) => {
          const tissueDisplayName = this.getTissueDisplayName(expr.tissueSiteDetailId);
          output += `  ${index + 1}. **${tissueDisplayName}**: ${expr.median.toFixed(3)} ${expr.unit}\n`;
        });
    
        if (sortedExpressions.length > topCount) {
          output += `  ... and ${sortedExpressions.length - topCount} more tissues\n`;
        }
    
        // Expression summary
        const medians = sortedExpressions.map(e => e.median);
        const expressionStats = {
          max: Math.max(...medians),
          min: Math.min(...medians),
          mean: medians.reduce((sum, val) => sum + val, 0) / medians.length,
          nonZeroCount: medians.filter(val => val > 0).length
        };
    
        output += `\n**Expression Summary:**\n`;
        output += `  • Tissues analyzed: ${sortedExpressions.length}\n`;
        output += `  • Highest expression: ${expressionStats.max.toFixed(3)} ${sortedExpressions[0]?.unit || 'TPM'}\n`;
        output += `  • Mean expression: ${expressionStats.mean.toFixed(3)} ${sortedExpressions[0]?.unit || 'TPM'}\n`;
        output += `  • Tissues with detectable expression: ${expressionStats.nonZeroCount}\n\n`;
      });
    
      return {
        content: [{
          type: "text",
          text: output.trim()
        }]
      };
    }
  • Tool schema definition in the listTools response, specifying the name, description, and input schema (gencodeId required, datasetId optional). Note: handler adapts 'gencodeId' to 'geneIds' array.
      name: "get_median_gene_expression",
      description: "Get median gene expression levels across tissues",
      inputSchema: {
        type: "object",
        properties: {
          gencodeId: {
            type: "string",
            description: "GENCODE gene ID (e.g., ENSG00000223972.5)"
          },
          datasetId: {
            type: "string",
            description: "GTEx dataset ID (default: gtex_v8)",
            default: "gtex_v8"
          }
        },
        required: ["gencodeId"]
      }
    },
  • src/index.ts:631-635 (registration)
    Tool call dispatching logic in the main CallToolRequestHandler. Matches tool name and invokes the expressionHandlers.getMedianGeneExpression method with adapted arguments.
    if (name === "get_median_gene_expression") {
      return await expressionHandlers.getMedianGeneExpression({
        geneIds: args?.gencodeId ? [args.gencodeId] : [],
        datasetId: args?.datasetId
      });
  • Supporting API client method that makes the HTTP request to GTEx Portal's /expression/medianGeneExpression endpoint, handling query params, response parsing, and error formatting.
    async getMedianGeneExpression(
      gencodeIds: string[],
      datasetId: string = 'gtex_v8',
      tissueSiteDetailIds?: string[]
    ): Promise<GTExApiResponse<MedianGeneExpression[]>> {
      try {
        const queryParams = this.buildQueryParams({
          gencodeId: gencodeIds,
          datasetId,
          tissueSiteDetailId: tissueSiteDetailIds,
          page: 0,
          itemsPerPage: 1000
        });
        const response = await this.axiosInstance.get(`/expression/medianGeneExpression?${queryParams}`);
        return { 
          data: response.data.data,
          paging_info: response.data.paging_info
        };
      } catch (error) {
        return error as GTExApiResponse<MedianGeneExpression[]>;
      }
    }

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