About gnomad-genetics-mcp-server
An MCP server for population genetics research using gnomAD data joined with ClinVar significance. It provides variant frequencies, gene constraint, variant catalogs, coverage, and SQL analysis of staged result sets.
Key features
- 01Inspect ancestry-specific variant frequencies
- 02Retrieve gene constraint metrics
- 03List variants and sequencing coverage
- 04Search ClinVar classifications
- 05Query staged results with SQL
- 06Use guided variant-triage prompt
Use cases
- 01Compare variant frequencies across ancestries
- 02Assess gene loss-of-function constraint
- 03Review variants and sequencing callability
- 04Analyze large result sets with SQL
MCP support
Exposes genetics tools, variant and gene resources, and a variant-triage prompt to MCP clients. The server supports STDIO and Streamable HTTP.
Configuration
Remote servers need no local install. Pick your client, then copy the config or install in one click.
https://gnomad-genetics.caseyjhand.com/mcpclaude mcp add --transport http cyanheads-gnomad-genetics https://gnomad-genetics.caseyjhand.com/mcp{"mcpServers":{"cyanheads-gnomad-genetics":{"type":"http","url":"https://gnomad-genetics.caseyjhand.com/mcp"}}}Open in Cursor{"servers":{"cyanheads-gnomad-genetics":{"type":"http","url":"https://gnomad-genetics.caseyjhand.com/mcp"}}}Open in VS Code{"mcpServers":{"cyanheads-gnomad-genetics":{"type":"http","url":"https://gnomad-genetics.caseyjhand.com/mcp"}}}{"mcpServers":{"cyanheads-gnomad-genetics":{"serverUrl":"https://gnomad-genetics.caseyjhand.com/mcp"}}}Run commands in a terminal; paste JSON into the client’s MCP config and restart. Servers that need sign-in will prompt on first connect.
Tools
7| Parameter | Type | Required | Description |
|---|---|---|---|
| dataset | enum | No | gnomAD dataset: gnomad_r4 (GRCh38, default), gnomad_r3 (GRCh38), gnomad_r2_1 (GRCh37), exac (GRCh37). Echoed in output.gnomad_r4 | gnomad_r3 | gnomad_r2_1 | exac |
| variants | array | Yes | 1–25 variant IDs (chrom-pos-ref-alt or rsID) to look up in one batched call. |
| reference_genome | enum | No | Reference build. Derived from dataset when omitted (v4/v3=GRCh38, v2.1/ExAC=GRCh37). If supplied it must match the dataset, or the call is rejected. Keep aligned with ensembl coordinates.GRCh38 | GRCh37 |
Details
From the project README@cyanheads/gnomad-genetics-mcp-server
Ancestry allele frequencies, LoF constraint, variant lists, and coverage from gnomAD, joined with ClinVar clinical significance via MCP. STDIO or Streamable HTTP.
Public Hosted Server: https://gnomad-genetics.caseyjhand.com/mcp
Overview
Population genetics over gnomAD (Broad Institute), with ClinVar clinical significance joined in from NCBI. Look up per-ancestry allele frequencies, gene loss-of-function constraint, gene variant catalogs, and sequencing coverage, then query large result sets with SQL.
Tools
| Tool | Description |
|---|---|
gnomad_get_variant | Full population record for one or more variants — AC/AN/AF overall and per genetic-ancestry group, homozygote/hemizygote counts, quality flags, transcript consequence, in-silico predictors, and joined ClinVar significance. |
gnomad_get_gene_constraint | Gene loss-of-function constraint — pLI, LOEUF (oe_lof_upper) with confidence interval, observed/expected ratios, and Z-scores. By HGNC symbol or Ensembl gene ID. |
gnomad_list_gene_variants | Every variant in a gene, transcript, or region with allele frequencies and predicted consequences, filterable by consequence class and max allele frequency. |
gnomad_get_coverage | Sequencing coverage across a gene, transcript, or region — mean/median depth and the fraction of samples over depth thresholds, per callset track. |
gnomad_search_clinvar | Gene-level ClinVar detail via NCBI E-utilities — classified variants, review status, conditions, submission counts, and gnomAD-compatible variant IDs, paged by offset. |
gnomad_dataframe_query | Run a read-only SQL SELECT across canvas tables staged by the list tools. |
gnomad_dataframe_describe | List the tables staged on a canvas and their columns before writing SQL. |
gnomad_dataframe_drop | Drop a named table from a canvas to reclaim memory. Opt-in via GNOMAD_DATAFRAME_DROP_ENABLED=true — off by default. |
Resources
| Resource | Description |
|---|---|
gnomad://variant/{dataset}/{variantId} | Population record for one variant — mirrors gnomad_get_variant. |
gnomad://gene/{dataset}/{gene}/constraint | Gene loss-of-function constraint — mirrors gnomad_get_gene_constraint. |
All resource data is also reachable via tools. The list tools (gnomad_list_gene_variants, gnomad_get_coverage, gnomad_search_clinvar) return analytical row sets rather than stable single-URI documents, so they are not exposed as resources — call the tools instead.
Upstream-backed tools and resource reads share one fixed 45 s deadline across queue waits, retries, response bodies, and chained requests. A variant batch shares that deadline across every item: completed results remain available and unfinished primary items report upstream_timeout. Caller cancellation rejects the call.
Prompts
| Prompt | Description |
|---|---|
gnomad_variant_triage | Guided rare-disease variant-triage workflow: population frequency → gene constraint → callability check, in order. |
Capability reference
gnomad_get_variant tool
- Up to 25 IDs per call (raise via
GNOMAD_MAX_VARIANT_BATCH), each achrom-pos-ref-altvariantId on chromosome1–22,X, orYwith an optionalchrprefix (e.g.1-55051215-G-GA) or an rsID (e.g.rs11591147) - A bad or absent ID lands in
failed[]as{ variant, error, reason, recovery }without failing the rest; mitochondrial IDs (M,MT,chrM) fail asmitochondrial_unsupported, and an ambiguous rsID addscandidates - Returns the full per-ancestry frequency vector, the callset(s) carrying the variant, quality flags, consequence, predictor scores, and ClinVar significance. A validated population record survives ClinVar-only failure or expiry with
clinvar: nullandclinvar_unavailable: true - Inspect each
failed[].reason: onlyvariant_not_foundreports absence from the chosen dataset; timeouts and other failures leave presence unknown. Checkgnomad_get_coveragebefore interpreting an absent variant
gnomad_get_gene_constraint tool
-
Accepts an HGNC symbol (
PCSK9) or an Ensembl gene ID (ENSG00000169174) -
Returns pLI (>0.9 intolerant), LOEUF /
oe_lof_upperwith its lower bound, observed/expected ratios for LoF / missense / synonymous, the three Z-scores, andconstraint_flags(e.g.no_exp_lof,syn_outlier) -
constraint_releasenames the release the metrics come from. Many genes have null constraint, reported as null:datasetSource constraint_releaseLoF-intolerance guidance gnomad_r4GRCh38 gnomAD constraint gnomAD v4.1.2LOEUF < 0.45 gnomad_r3GRCh38 gnomAD constraint (gnomAD publishes no v3 constraint) gnomAD v4.1.2LOEUF < 0.45 gnomad_r2_1GRCh37 gnomAD constraint gnomAD v2.1.1LOEUF < 0.35 exacGRCh37 ExAC constraint ExAC r0.3pLI only -
On
exacthe ratios and LOEUF are null andconstraint_flagsis empty
gnomad_list_gene_variants tool
- Supply exactly one of
gene,transcript_id, orregion(chrom-start-stop, 1-based inclusive, chromosome1–22,X, orYwith an optionalchrprefix); a blankgeneortranscript_idcounts as omitted - A region must span less than 2,500,000 bp and hold at most ~30,000 variants, otherwise it fails as
invalid_regionorregion_too_large; mitochondrial targets fail asmitochondrial_unsupported - Optional filters: one
consequence_class(lof/missense/synonymous/other) and/or a maximum allele frequency - A result too large to inline is staged on the
gene_variantscanvas table, returned ascanvas_idandtable_namebeside a preview; inspect it withgnomad_dataframe_describeand query it withgnomad_dataframe_query. Passing acanvas_idalways writesgene_variantsthere, replacing the previous table. With the canvas disabled (CANVAS_PROVIDER_TYPE=none), only the capped preview is returned
gnomad_get_coverage tool
- Supply exactly one of
gene,transcript_id, orregion(samechrom-start-stopform and 2,500,000 bp limit asgnomad_list_gene_variants); a blankgeneortranscript_idcounts as omitted. Bad regions fail asinvalid_regionorregion_too_large, and mitochondrial targets asmitochondrial_unsupported - Returns mean and median read depth plus the mean fraction of samples covered at each threshold (1× through 100×), summarized per callset track, with
bucket_size,bucket_count, observedpositions, totaltarget_positions, and unobservedmissing_positionsfor each. Missing bases leave callability unknown; statistics describe only returned buckets, with no invented zero depths coverage_sourcenarrows to one track (exome/genome); omit to return every available track- Notices disclose partial targets and missing supported tracks. An explicitly requested unsupported track is identified separately (v3 has genome only; ExAC has exome only)
gnomad_search_clinvar tool
- Takes an HGNC symbol only (an Ensembl gene ID returns guidance and searches nothing). Optional filters:
clinical_significance(e.g.pathogenic) andmin_review_stars(0–4) - Returns clinical significance, review status with a 0–4 star rating, conditions, molecular consequences, submission counts, and gnomAD-compatible identifiers (
canonical_spdi,rsids,grch38_variant_id). IDs ClinVar has no summary for are listed inunavailable_ids - Pages up to 500 records per call with
offset/limit(1–500);total_found,truncated, andnext_offsetsay whether more remain.limitcounts records before the filters, so a window can return fewer rows - A window too large to inline is staged on the
clinvar_variantscanvas table (query it withgnomad_dataframe_describeandgnomad_dataframe_query); passing acanvas_idalways writes it there, replacing the previous table.NCBI_API_KEYraises the rate limit from 3 to 10 req/s
gnomad_dataframe_query tool
- Runs single-statement, read-only SQL
SELECTs against a table staged bygnomad_list_gene_variantsorgnomad_search_clinvar(gene_variantsorclinvar_variants); writes, DDL, and file/HTTP table functions are rejected - Pages with
offset(default 0) andlimit(default 100, max 500); returnsrows,columns,total,truncated, andnext_offset(follow it untilnull). Use anORDER BYon a unique key for stable paging, and filter or aggregate in SQL to get past theCANVAS_DEFAULT_ROW_LIMITcap (10,000 by default) - A row over the 10,000-character page budget fails with
row_too_large; withCANVAS_PROVIDER_TYPE=noneit fails withcanvas_disabled
gnomad_dataframe_describe tool
- Lists every table staged on a canvas with its row count and column schema (name and DuckDB type)
- Call it before writing SQL for
gnomad_dataframe_query - Fails with a
canvas_disablederror when the canvas is turned off (CANVAS_PROVIDER_TYPE=none)
gnomad_dataframe_drop tool
- Drops a named table from a canvas to reclaim memory (
destructiveHint: true) - Opt-in via
GNOMAD_DATAFRAME_DROP_ENABLED=true; absent fromtools/listwhen off - An unknown or expired
canvas_idfails ascanvas_not_found; withCANVAS_PROVIDER_TYPE=noneit fails withcanvas_disabled
gnomad://variant/{dataset}/{variantId} resource
- Population record for one variant as
application/json, mirroringgnomad_get_variant;variantIdtakes a chrom-pos-ref-alt ID or an rsID - Typed errors:
invalid_variant_id,mitochondrial_unsupported,variant_not_found,ambiguous_rsid(withcandidates),graphql_error,upstream_build_mismatch,upstream_unavailable,upstream_timeout,upstream_access, andinvalid_upstream_response, each with a recovery hint
gnomad://gene/{dataset}/{gene}/constraint resource
- Gene loss-of-function constraint as
application/json, mirroringgnomad_get_gene_constraint(sameconstraint_releaseperdataset);genetakes an HGNC symbol or Ensembl gene ID - Typed errors:
gene_not_found,invalid_constraint_data,graphql_error,upstream_unavailable,upstream_timeout,upstream_access, andinvalid_upstream_response, each with a recovery hint
gnomad_variant_triage prompt
- Arguments:
variantrequired (chrom-pos-ref-alt or rsID; a malformed one is rejected);geneanddatasetoptional.datasetis one ofgnomad_r4,gnomad_r3,gnomad_r2_1,exac, and the server default applies when omitted - Emits a three-step chain as one user message: population frequency (
gnomad_get_variant) → gene constraint (gnomad_get_gene_constraint) → callability check (gnomad_get_coverageon the exact position)
Features
Built on @cyanheads/mcp-ts-core: stdio and Streamable HTTP transports, pluggable auth (none / jwt / oauth), swappable storage (in-memory, filesystem, Supabase, Cloudflare KV/R2/D1), structured logging with optional OpenTelemetry tracing.
gnomAD-specific:
- Single keyless GraphQL source for the entire core surface — ClinVar significance is joined per variant inside gnomAD's own response
datasetandreference_genomeare distinct, coherence-validated parameters (v4/v3 ⇒ GRCh38, v2.1/ExAC ⇒ GRCh37); both are echoed in every tool's output so a wrong-build coordinate mismatch is visible- Polite client — conservative concurrency cap (
GNOMAD_MAX_CONCURRENCY, default 2) and exponential backoff against a community-funded, rate-limited API - In-conversation SQL analytics:
gnomad_list_gene_variantsandgnomad_search_clinvarstage results too large to inline on a DuckDB-backed canvas table —gnomad_dataframe_describelists its columns,gnomad_dataframe_queryruns SQL over every row
Agent-friendly output:
- Per-ancestry allele-frequency vector returned in full, never collapsed to a single global AF
gnomad_get_variantreturns per-itemfailed[]rows instead of failing the whole batch- Effective
datasetandreference_genomeechoed on every response; null upstream fields stay null - Every error carries a typed
reason(e.g.incoherent_build,invalid_target,variant_not_found,upstream_timeout,canvas_disabled) and a recovery hint
Getting started
Public Hosted Instance
A public instance is available at https://gnomad-genetics.caseyjhand.com/mcp — no installation required. It serves Streamable HTTP; each client takes its own config shape.
For Claude Code:
claude mcp add --transport http gnomad-genetics-mcp-server https://gnomad-genetics.caseyjhand.com/mcp
For Cline (cline_mcp_settings.json):
{
"mcpServers": {
"gnomad-genetics-mcp-server": {
"type": "streamableHttp",
"url": "https://gnomad-genetics.caseyjhand.com/mcp"
}
}
}
For Cursor (mcp.json):
{
"mcpServers": {
"gnomad-genetics-mcp-server": {
"url": "https://gnomad-genetics.caseyjhand.com/mcp"
}
}
}
Claude Desktop adds remote servers under Settings → Connectors.
Self-Hosted / Local
Add the following to your MCP client configuration file. gnomAD is a free, keyless API — no credentials required.
{
"mcpServers": {
"gnomad-genetics-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/gnomad-genetics-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with npx (no Bun required):
{
"mcpServers": {
"gnomad-genetics-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/gnomad-genetics-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with Docker:
{
"mcpServers": {
"gnomad-genetics-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"ghcr.io/cyanheads/gnomad-genetics-mcp-server:latest"
]
}
}
}
For Streamable HTTP, set the transport and start the server:
MCP_TRANSPORT_TYPE=http MCP_HTTP_PORT=3010 bun run start:http
# Server listens at http://localhost:3010/mcp
The SQL analytics path runs on DuckDB by default — @duckdb/node-api ships as a dependency, so nothing extra to install. Set CANVAS_PROVIDER_TYPE=none to turn it off. The Claude Desktop bundle (.mcpb) ships without DuckDB's native bindings and runs with the canvas off.
Prerequisites
- Bun v1.4.0 or higher (or Node.js v24+).
- No API key — gnomAD's GraphQL endpoint is keyless. An optional
NCBI_API_KEYraises thegnomad_search_clinvarrate limit.
Installation
- Clone the repository:
git clone https://github.com/cyanheads/gnomad-genetics-mcp-server.git
- Navigate into the directory:
cd gnomad-genetics-mcp-server
- Install dependencies:
bun install
- Configure environment:
cp .env.example .env
# all vars are optional — the server runs keyless out of the box
Configuration
All variables are optional; the server runs keyless with the defaults below.
Node and Bun load the working directory's .env before building tool definitions. Exported values take precedence; blank values use the schema defaults. The advertised variant cap, its input validation, and the drop-tool registration gate use those same settings. Invalid server configuration fails startup with a banner naming the variable; DEBUG=true includes the stack.
| Variable | Description | Default |
|---|---|---|
GNOMAD_API_BASE_URL | gnomAD GraphQL endpoint. Override for a private mirror or testing. | https://gnomad.broadinstitute.org/api |
GNOMAD_DEFAULT_DATASET | Dataset used when a tool call omits dataset (gnomad_r4 / gnomad_r3 / gnomad_r2_1 / exac). | gnomad_r4 |
GNOMAD_REQUEST_TIMEOUT_MS | Per-attempt gnomAD/NCBI timeout in milliseconds, bounded by the shared 45 s call deadline. | 30000 |
GNOMAD_MAX_CONCURRENCY | Cap on concurrent upstream requests — politeness against a community-funded API. | 2 |
GNOMAD_MAX_VARIANT_BATCH | Maximum variant IDs accepted per gnomad_get_variant call. | 25 |
CLINVAR_BASE_URL | NCBI E-utilities base URL for gnomad_search_clinvar. | https://eutils.ncbi.nlm.nih.gov/entrez/eutils |
NCBI_API_KEY | Optional NCBI key. Raises the E-utilities rate limit from 3 to 10 req/s. | — |
CANVAS_PROVIDER_TYPE | DataCanvas backend for the spill/SQL path behind the list tools. none disables it, and the list tools then return a capped inline preview. | duckdb |
GNOMAD_DATAFRAME_DROP_ENABLED | Gate for the opt-in gnomad_dataframe_drop tool. Off by default. | false |
MCP_TRANSPORT_TYPE | Transport: stdio or http. | stdio |
MCP_HTTP_PORT | Port for the HTTP server. | 3010 |
MCP_AUTH_MODE | Auth mode: none, jwt, or oauth. | none |
MCP_LOG_LEVEL | Log level (RFC 5424). | info |
OTEL_ENABLED | Enable OpenTelemetry instrumentation. | false |
See .env.example for the full list of optional overrides.
Running the server
Local development
-
Build and run:
# One-time build bun run rebuild # Run the built server bun run start:stdio # or bun run start:http -
Run checks and tests:
bun run devcheck # Lint, format, typecheck, security bun run test # Vitest test suite bun run lint:mcp # Validate MCP definitions against spec
Docker
docker build -t gnomad-genetics-mcp-server .
docker run --rm -e MCP_TRANSPORT_TYPE=http -p 3010:3010 gnomad-genetics-mcp-server
The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/gnomad-genetics-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
Project structure
| Directory | Purpose |
|---|---|
src/index.ts | createApp() entry point — registers tools/resources/prompts and inits services. |
src/config | Server-specific environment variable parsing and validation with Zod. |
src/mcp-server/tools | Tool definitions (*.tool.ts) and shared input schemas. |
src/mcp-server/resources | Resource definitions (*.resource.ts). |
src/mcp-server/prompts | Prompt definitions (*.prompt.ts). |
src/services/gnomad | gnomAD GraphQL client, query documents, and domain types. |
src/services/clinvar | NCBI E-utilities client for the optional ClinVar tool. |
src/services/canvas-accessor.ts | Module-level accessor for the framework's optional DataCanvas. |
Development guide
See CLAUDE.md/AGENTS.md for development guidelines and architectural rules. The short version:
- Handlers throw, framework catches — no
try/catchin tool logic - Use
ctx.logfor request-scoped logging,ctx.statefor tenant-scoped storage - Register new tools and resources in the
createApp()arrays insrc/index.ts - Wrap external API calls: validate raw → normalize to domain type → return output schema; never fabricate missing fields
Data attribution
gnomAD data is provided by the Genome Aggregation Database (Broad Institute). ClinVar data is provided by NCBI.
Contributing
Issues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
License
Apache-2.0 — see LICENSE for details.
Comments
New to MCP?
From what the protocol is to installing your first server, these answers cover most first questions.
An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.