Look up genes, sequences, variants, homologs, and cross-database xrefs from Ensembl REST.
One address for any MCP client. No sign-in needed on this server.
6 read1 other
Grouped by tool name. At most: only reads or looks up information.
Odel charges nothing per call. The publisher may charge for its own service.
Look up genes, fetch sequences, predict variant consequences, find orthologs, and retrieve cross-database xrefs from Ensembl REST via MCP. STDIO or Streamable HTTP.
Public Hosted Server: https://ensembl.caseyjhand.com/mcp
Gene, sequence, and variant data for vertebrates and other model organisms from the Ensembl REST API. Look up genes, fetch sequences, predict variant consequences, find orthologs, and cross-reference external databases.
| Tool | Description |
|---|---|
ensembl_list_species | List species supported by Ensembl with display name, common name, assembly, taxon ID, and division |
ensembl_lookup_gene | Resolve a gene by symbol (synonyms and former symbols included) + species or by stable ID to its Ensembl ID, genomic location, biotype, and transcript list |
ensembl_get_sequence | Fetch the DNA, cDNA, CDS, or protein sequence for a gene, transcript, protein, or genomic region |
ensembl_query_region | Find genomic features (genes, transcripts, variants, regulatory elements, exons) overlapping a chromosomal region |
ensembl_predict_variant | Predict functional consequences of a sequence variant using the Ensembl Variant Effect Predictor (VEP) |
ensembl_get_homology | Find orthologs and/or paralogs of a gene across species with percent identity and taxonomy level |
ensembl_get_xrefs | Retrieve cross-database references for a gene — HGNC, UniProt, EntrezGene, OMIM, RefSeq, Reactome, and others |
| Resource | Description |
|---|---|
ensembl://gene/{id} | Gene record by stable ID (ENSG…) — location, biotype, description, and transcript list |
ensembl://transcript/{id} | Transcript record by stable ID (ENST…) — parent gene, location, biotype, canonical flag, and length |
ensembl://species | Supported Ensembl species for the endpoint default division (vertebrates on the default endpoint) |
ensembl://species/{division} | Supported species in one division (EnsemblVertebrates, EnsemblPlants, EnsemblFungi, EnsemblMetazoa, EnsemblProtists) |
The species resources return the first 50 species by internal name; the ensembl_list_species tool pages through the rest and filters by name.
| Prompt | Description |
|---|---|
ensembl_gene_dossier | Structured workflow for assembling a complete gene profile: symbol → ID + location → sequence → variants → orthologs → xrefs |
Ensembl's stable-ID endpoints answer a versioned ID (ENSG00000139618.19) as not found, so every tool and resource that takes an Ensembl stable ID drops a trailing .N from an ENS… ID before the request and returns the current version. HGVS input to ensembl_predict_variant (ENST00000380152.8:c.2T>A) keeps its version, and IDs from other sources (AT3G52430.1) are forwarded unchanged.
ensembl_list_species tooldivision (EnsemblVertebrates, EnsemblPlants, EnsemblFungi, EnsemblMetazoa, EnsemblProtists; omitted, the endpoint default — vertebrates, ~356 species on GRCh38) and nameContains, a substring match against name, display name, and common namehomo_sapiens), plus display name, common name, taxon ID, assembly, and divisionoffset (default 0) and max_results (default 50, 0 uncapped); totalCount reports every match, and nextOffset is where the next page starts when more followensembl_lookup_gene toolsymbol (+ species, default homo_sapiens), id, ids, or symbols (up to 1,000 submitted items; first 20 distinct trimmed queries processed); expand_transcripts (default false) adds the transcript list with biotype and canonical flagcanonicalTranscript identifies the canonical transcript without expansion; transcript-ID lookups also return parentGeneId. Expanded transcripts include maneSelect RefSeq accessions when available (BRCA2: ENST00000380152.8, NM_000059.4)HER2 → ERBB2), reported as matchedAlias; a name shared by several genes (MDR1) returns ambiguous with candidates to retry by idgene (or ambiguous); a batch returns ordered succeeded items carrying the submitted query, failed items with query, reason (not_found, ambiguous with candidates, or unavailable), error, and recovery, and omitted queries past the processing cap. Omitted queries are never requested or reported as failed; resubmit them separately. Errors: not_found, invalid_species, no_input, conflicting_inputensembl_get_sequence toolENSG…/ENST…/ENSP…) or a region (species:chr:start-end, or chr:start-end with species; at most 10,000,000 bases); type is genomic (default), cdna, cds, or protein — cdna and cds from a transcript ID only, protein from a transcript or protein ID; expand_5prime/expand_3prime add flanking bases:1/:-1 strand suffix (1:1000000-1000020:-1 returns the reverse complement); the mitochondrion is MT in vertebrates (mitochondrion_genome in Drosophila, MtDNA in C. elegans), and M/chrM are rejected as invalid_region where they would not resolve to itoffset (default 0) and max_length (default 10000, 0 uncapped); length is the full sequence length, and truncated/nextOffset say where to resumenot_found, type_mismatch (also a protein ID asked for genomic/cdna/cds, or a non-coding transcript asked for protein/cds), invalid_species, missing_species, invalid_region (also an id with a colon that is not a valid region)ensembl_query_region toolregion as species:chr:start-end, or chr:start-end with species (at most 5,000,000 bases; reversed coordinates are rejected; mitochondrion naming as in ensembl_get_sequence); feature defaults to ["gene"] and also accepts transcript, variation, regulatory, exon; optional case-sensitive biotype filter (protein_coding, lncRNA). An empty filtered result suggests removing the filter without inferring the locus is intergenicmax_results caps the list (default 100, 0 uncapped) while totalCount reports the true count; assemblyName names the coordinates' assembly, and exon rows carry parentId and rank. Errors: invalid_region, invalid_species, missing_speciesensembl_predict_variant toolvariant as HGVS (transcript-relative or genomic), region+allele (chr:start:end:strand/allele), or a dbSNP rsIDinvalid_notation, not_found, invalid_speciesvariantAllele, optional canonical/maneSelect, HGVS and available SIFT/PolyPhen prediction-score pairs; records retain alleleStringclinicalSignificance is aggregate, not a classification of the submitted allele. clinicalSignificanceByAllele preserves explicit per-allele terms and clinicalSignificanceReferenceAllele identifies their reference allele; absent annotations remain omittedmax_transcript_consequences and max_pubmed_ids_per_variant (default 10 each, 0 uncapped; include_all_colocated_pubmed lifts the PubMed cap) bound the result, while transcriptConsequencesTotal and pubmedTotal report the full countsensembl_get_homology toolsymbol (+ species, default homo_sapiens) or id; type is orthologues (default), paralogues, or all; optional target_species filtermax_results caps the list (default 25, 0 uncapped) while totalCount reports the true count. Errors: not_found, invalid_species (unknown species or target_species), no_input, conflicting_inputtargetProteinId for ensembl_get_sequence with type:"protein". Optional targetSymbol comes from a lookup of the returned rows' distinct gene IDs, in chunks of at most 1,000, with one five-second budget bounded by the call's remaining deadline and no retries. Missing names or failed lookups retain every primary homolog with a notice; cancellation still abortsensembl_get_xrefs toolid (ENSG…/ENST…/ENSP…) required; optional dbname filter (e.g. HGNC, Uniprot_gn, EntrezGene, MIM_GENE, RefSeq_mRNA, Reactome_gene for gene pathways, Reactome for translation pathways, GO)all_levels:false queries the requested object's level. Set all_levels:true to include a gene's transcript and translation references, independently of dbname; for example, gene-level RefSeq_mRNA may need this or a transcript ID. Empty lists remain successful with totalCount:0. Errors: not_foundensembl://gene/{id} resourceid is a gene stable ID (ENSG…); a version suffix is optional and droppednot_foundensembl://transcript/{id} resourceid is a transcript stable ID (ENST…); a version suffix is optional and droppednot_foundensembl://species resourcetotalCount, shown, and truncated; a truncated body's notice points to ensembl_list_species (offset, max_results) for the restensembl://species/{division} insteadensembl://species/{division} resourcedivision required: EnsemblVertebrates, EnsemblPlants, EnsemblFungi, EnsemblMetazoa, or EnsemblProtiststotalCount, shown, and truncated; a truncated body's notice points to ensembl_list_species (division, offset, max_results) for the restensembl_gene_dossier promptgene_symbol required; species optional (default homo_sapiens)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.
Ensembl-specific:
Retry-After) and transient 5xx errorsPOST /lookup/id and POST /lookup/symbol/{species} to avoid N+1 round tripsENSEMBL_BASE_URL — point the entire server at https://grch37.rest.ensembl.org for clinical workflows on the older assemblyAgent-friendly output:
ensembl_get_sequence returns bounded windows (10,000 characters by default) with the full length and a nextOffset to continueensembl_list_species is the discovery step for internal species names, 50 per page with a nextOffsetensembl_get_xrefs are described as inputs for protein and literature servers; the ensembl_gene_dossier prompt chains 6 of the 7 toolsA public instance is available at https://ensembl.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 ensembl-mcp-server https://ensembl.caseyjhand.com/mcp
For Cline (cline_mcp_settings.json):
{
"mcpServers": {
"ensembl-mcp-server": {
"type": "streamableHttp",
"url": "https://ensembl.caseyjhand.com/mcp"
}
}
}
For Cursor (mcp.json):
{
"mcpServers": {
"ensembl-mcp-server": {
"url": "https://ensembl.caseyjhand.com/mcp"
}
}
}
Claude Desktop adds remote servers under Settings → Connectors.
Add the following to your MCP client configuration file.
{
"mcpServers": {
"ensembl-mcp-server": {
"type": "stdio",
"command": "bunx",
"args": ["@cyanheads/ensembl-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with npx (no Bun required):
{
"mcpServers": {
"ensembl-mcp-server": {
"type": "stdio",
"command": "npx",
"args": ["-y", "@cyanheads/ensembl-mcp-server@latest"],
"env": {
"MCP_TRANSPORT_TYPE": "stdio",
"MCP_LOG_LEVEL": "info"
}
}
}
}
Or with Docker:
{
"mcpServers": {
"ensembl-mcp-server": {
"type": "stdio",
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "MCP_TRANSPORT_TYPE=stdio",
"ghcr.io/cyanheads/ensembl-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
git clone https://github.com/cyanheads/ensembl-mcp-server.git
cd ensembl-mcp-server
bun install
cp .env.example .env
# edit .env if you need to override ENSEMBL_BASE_URL (e.g. for GRCh37)
All configuration is validated at startup via Zod schemas in src/config/server-config.ts.
| Variable | Description | Default |
|---|---|---|
ENSEMBL_BASE_URL | Ensembl REST API base URL. Override for GRCh37 (https://grch37.rest.ensembl.org) or a local mirror. | https://rest.ensembl.org |
MCP_TRANSPORT_TYPE | Transport: stdio or http | stdio |
MCP_HTTP_PORT | HTTP server port | 3010 |
MCP_HTTP_ENDPOINT_PATH | HTTP endpoint path | /mcp |
MCP_SESSION_MODE | HTTP session mode: auto, stateful, or stateless | stateless |
MCP_AUTH_MODE | Authentication: none, jwt, or oauth | none |
MCP_LOG_LEVEL | Log level (debug, info, warning, error, etc.) | info |
LOGS_DIR | Directory for log files (Node.js only) | <project-root>/logs |
LOG_TOOL_FAILURE_PAYLOADS | Log each failed tool call's arguments and result, redacted by key name and capped at LOG_TOOL_FAILURE_PAYLOAD_MAX_BYTES (default 16384). A secret inside a free-form value is not redacted. | false |
OTEL_ENABLED | Enable OpenTelemetry | false |
See .env.example for the full list of optional overrides.
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 build -t ensembl-mcp-server .
docker run --rm -p 3010:3010 ensembl-mcp-server
The Dockerfile defaults to HTTP transport, stateless session mode, and logs to /var/log/ensembl-mcp-server. OpenTelemetry peer dependencies are installed by default — build with --build-arg OTEL_ENABLED=false to omit them.
| 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) — 7 tools |
src/mcp-server/resources | Resource definitions (*.resource.ts) — gene, transcript, species |
src/mcp-server/prompts | Prompt definitions (*.prompt.ts) — gene dossier workflow |
src/services/ensembl | Ensembl REST API client — HTTP, rate-limit handling, retry, error normalization |
tests/ | Unit and integration tests mirroring src/ |
See CLAUDE.md for development guidelines and architectural rules. The short version:
try/catch in tool logicctx.log for request-scoped logging, ctx.state for tenant-scoped storagecreateApp() arrays in src/index.tsIssues are welcome. Run checks and tests before submitting:
bun run devcheck
bun run test
Apache-2.0 — see LICENSE for details.