Skip to main content
Glama

analyze_ld_structure

Analyze linkage disequilibrium patterns around eQTL variants to understand genetic associations and co-inheritance in specific genomic regions.

Instructions

Analyze linkage disequilibrium structure around eQTL variants

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
chrYesChromosome (e.g., chr1, chr2, chrX)
populationNoPopulation for LD analysis (default: EUR)EUR
positionYesGenomic position (1-based)
windowSizeNoWindow size around position (default: 100000)

Implementation Reference

  • The core handler function `analyzeLDStructure` that fetches variants in a genomic window around the given position using GTExApiClient.getVariants, identifies the closest variant to the query position, computes variant density in distance bins, lists top nearby common variants (MAF >=1%), and generates a formatted text output describing the local LD structure.
    async analyzeLDStructure(args: any) { if (!args.chr || !args.position) { throw new Error('chr and position parameters are required for LD analysis'); } if (typeof args.position !== 'number') { throw new Error('position parameter must be a number'); } const windowSize = args.windowSize || 100000; const population = args.population || 'EUR'; // For LD analysis, we need to get variants in the region first const variantResult = await this.apiClient.getVariants({ chromosome: args.chr, pos: [Math.max(1, args.position - windowSize), args.position + windowSize], datasetId: 'gtex_v8', page: 0, itemsPerPage: 100 }); if (variantResult.error) { return { content: [{ type: "text", text: `Error retrieving variants for LD analysis: ${variantResult.error}` }], isError: true }; } const variants = variantResult.data || []; if (variants.length === 0) { return { content: [{ type: "text", text: `No variants found in region ${args.chr}:${args.position - windowSize}-${args.position + windowSize}` }] }; } // Find the closest variant to the query position let closestVariant = variants[0]; let minDistance = Math.abs(closestVariant.pos - args.position); variants.forEach(variant => { const distance = Math.abs(variant.pos - args.position); if (distance < minDistance) { minDistance = distance; closestVariant = variant; } }); let output = `**Linkage Disequilibrium Structure Analysis**\n`; output += `Query Position: ${args.chr}:${args.position.toLocaleString()}\n`; output += `Analysis Window: ±${windowSize.toLocaleString()} bp\n`; output += `Population: ${population}\n`; output += `Variants Found: ${variants.length}\n\n`; output += `**Closest Variant to Query:**\n`; output += `• **${closestVariant.variantId}**\n`; output += ` - Position: ${args.chr}:${closestVariant.pos.toLocaleString()}\n`; output += ` - Distance: ${minDistance.toLocaleString()} bp\n`; output += ` - Alleles: ${closestVariant.ref} → ${closestVariant.alt}\n`; if (closestVariant.snpId && closestVariant.snpId !== 'nan') { output += ` - rsID: ${closestVariant.snpId}\n`; } output += ` - MAF ≥1%: ${closestVariant.maf01 ? 'Yes' : 'No'}\n\n`; // Group variants by distance from query const distanceBins = { '<1kb': variants.filter(v => Math.abs(v.pos - args.position) < 1000).length, '1-10kb': variants.filter(v => Math.abs(v.pos - args.position) >= 1000 && Math.abs(v.pos - args.position) < 10000).length, '10-50kb': variants.filter(v => Math.abs(v.pos - args.position) >= 10000 && Math.abs(v.pos - args.position) < 50000).length, '50kb+': variants.filter(v => Math.abs(v.pos - args.position) >= 50000).length }; output += `**Variant Density by Distance:**\n`; Object.entries(distanceBins).forEach(([bin, count]) => { output += `• ${bin}: ${count} variants\n`; }); // Show nearby high-quality variants const nearbyVariants = variants .filter(v => Math.abs(v.pos - args.position) <= 50000) .filter(v => v.maf01) // Only common variants .sort((a, b) => Math.abs(a.pos - args.position) - Math.abs(b.pos - args.position)) .slice(0, 10); if (nearbyVariants.length > 0) { output += `\n**Nearby Common Variants (MAF ≥1%, within 50kb):**\n`; nearbyVariants.forEach((variant, index) => { const distance = Math.abs(variant.pos - args.position); output += `${(index + 1).toString().padStart(2)}. **${variant.variantId}**\n`; output += ` • Distance: ${distance.toLocaleString()} bp\n`; output += ` • Alleles: ${variant.ref} → ${variant.alt}\n`; if (variant.snpId && variant.snpId !== 'nan') { output += ` • rsID: ${variant.snpId}\n`; } }); } output += `\n**LD Analysis Notes:**\n`; output += `• This analysis identifies variants in the region for LD structure assessment\n`; output += `• True LD calculations require population genetics data (r² values)\n`; output += `• Consider using 1000 Genomes or gnomAD data for detailed LD analysis\n`; output += `• Variants with MAF ≥1% are generally suitable for LD calculations\n`; return { content: [{ type: "text", text: output }] }; }
  • The tool schema definition in the ListToolsRequestSchema response, specifying the name, description, and inputSchema with required parameters chr and position, optional windowSize and population.
    name: "analyze_ld_structure", description: "Analyze linkage disequilibrium structure around eQTL variants", inputSchema: { type: "object", properties: { chr: { type: "string", description: "Chromosome (e.g., chr1, chr2, chrX)" }, position: { type: "integer", description: "Genomic position (1-based)" }, windowSize: { type: "integer", description: "Window size around position (default: 100000)", default: 100000 }, population: { type: "string", description: "Population for LD analysis (default: EUR)", enum: ["EUR", "AFR", "AMR", "EAS", "SAS"], default: "EUR" } }, required: ["chr", "position"] } },
  • src/index.ts:705-712 (registration)
    The conditional dispatch in the CallToolRequestSchema handler that maps incoming tool call arguments to the AssociationHandlers.analyzeLDStructure method and executes it.
    if (name === "analyze_ld_structure") { return await associationHandlers.analyzeLDStructure({ chr: args?.chr, position: args?.position, windowSize: args?.windowSize, population: args?.population }); }

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