get_sample_info
Retrieve sample metadata and demographic information from the GTEx Portal for genomic analysis, supporting tissue-specific queries and dataset selection.
Instructions
Get GTEx sample metadata and demographics
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| tissueSiteDetailId | No | Tissue site detail ID (optional, for tissue-specific samples) | |
| datasetId | No | GTEx dataset ID (default: gtex_v8) | gtex_v8 |
Implementation Reference
- The core handler method getSamples() in ReferenceHandlers class that implements the logic for the get_sample_info tool. It fetches sample metadata from GTEx API, handles errors, and formats detailed or summary output based on result size.async getSamples(args: any) { const result = await this.apiClient.getSamples({ datasetId: args.datasetId || 'gtex_v8', sampleId: args.sampleIds, tissueSampleId: args.tissueSampleIds, subjectId: args.subjectIds, ageBracket: args.ageBrackets, sex: args.sex, pathCategory: args.pathCategories, tissueSiteDetailId: args.tissueIds, page: args.page || 0, itemsPerPage: args.itemsPerPage || 100 }); if (result.error) { return { content: [{ type: "text", text: `Error retrieving sample information: ${result.error}` }], isError: true }; } const samples = result.data || []; if (samples.length === 0) { return { content: [{ type: "text", text: "No samples found matching the specified criteria." }] }; } let output = `**Sample Information (${samples.length} samples)**\n`; output += `Dataset: ${samples[0]?.datasetId}\n\n`; if (samples.length <= 20) { // Detailed view for small result sets samples.forEach((sample, index) => { output += `### Sample ${index + 1}: ${sample.sampleId}\n`; output += `**Subject Information:**\n`; output += ` • Subject ID: ${sample.subjectId}\n`; output += ` • Age bracket: ${sample.ageBracket}\n`; output += ` • Sex: ${sample.sex}\n`; output += ` • Hardy Scale: ${sample.hardyScale}\n`; output += `\n**Sample Details:**\n`; output += ` • Tissue sample ID: ${sample.tissueSampleId}\n`; output += ` • Tissue: ${sample.tissueSiteDetail} (${sample.tissueSiteDetailId})\n`; if (sample.aliquotId) { output += ` • Aliquot ID: ${sample.aliquotId}\n`; } output += ` • Data type: ${sample.dataType}\n`; if (sample.ischemicTime !== undefined) { output += `\n**Sample Quality:**\n`; output += ` • Ischemic time: ${sample.ischemicTime} min (${sample.ischemicTimeGroup})\n`; if (sample.rin !== undefined) { output += ` • RIN: ${sample.rin}\n`; } if (sample.autolysisScore) { output += ` • Autolysis score: ${sample.autolysisScore}\n`; } } if (sample.pathologyNotes) { output += `\n**Pathology Notes:** ${sample.pathologyNotes}\n`; } output += '\n'; }); } else { // Summary view for large result sets const tissueGroups: { [key: string]: any[] } = {}; samples.forEach(sample => { if (!tissueGroups[sample.tissueSiteDetailId]) { tissueGroups[sample.tissueSiteDetailId] = []; } tissueGroups[sample.tissueSiteDetailId].push(sample); }); output += `**Sample Summary by Tissue:**\n`; Object.entries(tissueGroups).forEach(([tissueId, tissueSamples]) => { const tissueDisplayName = this.getTissueDisplayName(tissueId); const maleCount = tissueSamples.filter(s => s.sex === 'male').length; const femaleCount = tissueSamples.filter(s => s.sex === 'female').length; const avgAge = this.calculateAverageAge(tissueSamples); output += ` **${tissueDisplayName}** (${tissueSamples.length} samples)\n`; output += ` • Male: ${maleCount}, Female: ${femaleCount}\n`; if (avgAge) { output += ` • Average age: ${avgAge}\n`; } }); } if (result.paging_info && result.paging_info.totalNumberOfItems > samples.length) { output += `\n**Note:** Showing ${samples.length} of ${result.paging_info.totalNumberOfItems} total results.\n`; } return { content: [{ type: "text", text: output.trim() }] }; }
- src/index.ts:462-478 (schema)Input schema definition for the get_sample_info tool in the tools list returned by ListToolsRequestSchema.name: "get_sample_info", description: "Get GTEx sample metadata and demographics", inputSchema: { type: "object", properties: { tissueSiteDetailId: { type: "string", description: "Tissue site detail ID (optional, for tissue-specific samples)" }, datasetId: { type: "string", description: "GTEx dataset ID (default: gtex_v8)", default: "gtex_v8" } } } },
- src/index.ts:739-744 (registration)Dispatch registration in the CallToolRequestSchema handler that routes get_sample_info calls to the referenceHandlers.getSamples method.if (name === "get_sample_info") { return await referenceHandlers.getSamples({ tissueIds: args?.tissueSiteDetailId ? [args.tissueSiteDetailId] : undefined, datasetId: args?.datasetId }); }
- src/index.ts:23-44 (registration)Import and instantiation of ReferenceHandlers class used for get_sample_info tool execution.import { ReferenceHandlers } from "./handlers/reference-handlers.js"; import { GTExApiClient } from "./utils/api-client.js"; /** * Create an MCP server for GTEx Portal API access */ const server = new Server( { name: "gtex-server", version: "1.0.0", }, { capabilities: { tools: {}, }, } ); // Initialize handlers (they create their own API clients internally) const expressionHandlers = new ExpressionHandlers(); const associationHandlers = new AssociationHandlers(); const referenceHandlers = new ReferenceHandlers();