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
| Name | Required | Description | Default |
|---|---|---|---|
| gencodeId | Yes | GENCODE gene ID (e.g., ENSG00000223972.5) | |
| datasetId | No | GTEx 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() }] }; }
- src/index.ts:73-90 (schema)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 });
- src/utils/api-client.ts:302-323 (helper)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[]>; } }