orphanet-link
Read-only MCP server that answers rare-disease questions from a locally built Orphanet/Orphadata SQLite + FTS5 index.
Resolve free-text labels, synonyms, ORPHAcodes, or external CURIEs (OMIM, MONDO, ICD-10/11, UMLS, GARD, MeSH, MedDRA) to canonical Orphanet disorders.
Full-text search disease names/synonyms/definitions, with pagination and optional obsolete terms.
Fetch full disorder records: type/group, synonyms, grouped xrefs, classification parents/children, onset, inheritance, plus optional genes, phenotypes, prevalence, and disability in one call; sparse
fieldsprojection supported.Gene associations (symbol, HGNC id, type/status, PMIDs) and reverse lookup by HGNC gene symbol.
HPO phenotype annotations with frequency filtering and reverse lookup by HPO term.
Prevalence/epidemiology and natural-history data (age of onset, inheritance).
Functional-consequence/disability annotations with explicit coverage semantics.
Classification hierarchy: immediate parents/children and transitive ancestors/descendants via precomputed closure.
Cross-reference mapping grouped by source with mapping relations; resolve external CURIEs back to Orphanet disorders.
Batch resolve/fetch up to 50 items with per-item partial success.
Discovery/diagnostics: capabilities, tool signatures, workflows, error taxonomy, limits, Orphanet release, index status, runtime metrics.
All tools are read-only, support
response_modeminimal/compact/standard/full, return a success/_meta/payload-or-error envelope withnext_commands; research use only, not clinical decision support.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@orphanet-link show me the prevalence data for cystic fibrosis"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
orphanet-link
A read-only Model Context Protocol (MCP) server that grounds rare-disease questions in Orphanet's scientific knowledge files (Orphadata, INSERM), served from a locally-built SQLite + FTS5 index of the eight English Orphadata XML products.
Research use only. Not clinical decision support. Do not use for diagnosis, treatment, triage, or patient management.
Why
Orphadata ships its rare-disease knowledge as eight separate bulk XML products — nomenclature, cross-references, ~33 per-specialty classification files, gene associations, HPO phenotypes, epidemiology, natural history, functional consequences. They are a download, not a query surface: asking "which genes are linked to Aicardi syndrome, what is its prevalence, and what is it called in OMIM?" means fetching ~150 MB of XML, joining four products on ORPHAcode, and walking a poly-hierarchy by hand.
orphanet-link does that join once — into a normalized, read-only SQLite + FTS5 index with
precomputed classification closures — and serves it as MCP tools. A free-text label, a synonym, a
bare ORPHA code, or an external CURIE (OMIM, MONDO, ICD-10/11, UMLS, GARD, MeSH, MedDRA) all
resolve to the same canonical disorder, and every answer is reproducible against a stated Orphanet
release.
Related MCP server: hpo-link
Quick start
The GeneFoundry instance is hosted — no install:
claude mcp add --transport http orphanet-link https://orphanet-link.genefoundry.org/mcpLocally (Python 3.14+ and uv):
git clone https://github.com/berntpopp/orphanet-link.git
cd orphanet-link
uv sync --group dev
make data-fetch # pull the prebuilt SQLite index from the GitHub Release
make dev # unified REST + MCP → http://127.0.0.1:8000/mcp
claude mcp add --transport http orphanet-link http://127.0.0.1:8000/mcpThe server needs a database before it can answer. make data-fetch pulls the prebuilt one
published by CI; make data builds it from the Orphadata XML instead (~150 MB). Either way the
local server also bootstraps one on first start when none is present — see Data.
Production uses the hardened init sidecar to fetch and verify its pinned release before the app
starts with a read-only snapshot.
make dev runs --transport unified, the only mode that serves MCP; --transport http is
REST/health-only. make docker-up runs the container stack and prints its MCP URL. See
Deployment.
Tools
Every tool is read-only, accepts response_mode (minimal / compact / standard / full,
default compact), and returns the fleet's success / _meta / payload-or-error envelope.
_meta.next_commands carries ready-to-call follow-ups — see
Architecture & the MCP surface.
Tool | Purpose |
| Discovery: tool signatures, response modes, workflows, error taxonomy, limits, Orphanet release |
| Index status: Orphanet release, disorder counts, schema version, build time, runtime metrics |
| Free-text label, synonym, ORPHA code ( |
| FTS over disease names and synonyms; relevance-ranked, paginated, optional obsolete inclusion |
| Full disorder record: type/group, synonyms, grouped cross-references, classification parents/children, association counts; sparse |
| Gene associations: symbol, HGNC id, association type and status, source PMIDs, gene xrefs |
| HPO annotations: HPO id, term name, frequency category; optional frequency filter |
| Epidemiology: prevalence type, class band, numeric ValMoy, geography, validation status, source |
| Age-of-onset categories and inheritance patterns |
| Functional-consequence annotations: ability categories affected and severity grades |
| Immediate parents and children in Orphanet's poly-hierarchical classification trees |
| Transitive classification ancestors (precomputed closure), paginated |
| Transitive classification descendants (precomputed closure), paginated |
| A disorder's cross-references grouped by source (OMIM, MONDO, ICD-10/11, UMLS, GARD, MeSH, MedDRA) with mapping relations |
| External CURIE → matching Orphanet disorder(s), paginated |
| Reverse lookup: HGNC gene symbol → associated disorders, paginated |
| Reverse lookup: HPO term id → associated disorders, paginated |
| Batch-resolve up to |
| Batch-fetch up to |
Leaf names are intentionally unprefixed, per the fleet's Tool-Naming Standard v1. Behind
genefoundry-router this server mounts under the
orphanet namespace, so tools surface as orphanet_<tool> — e.g. orphanet_resolve_disease, the
pinned entry point.
Data & provenance
Source — Orphadata, the free-access scientific-knowledge file distribution of Orphanet (INSERM, Paris). Eight English XML products, downloaded directly with no authentication.
Refresh — Orphanet releases bi-annually. CI rebuilds the index weekly and publishes it as a
versioned data-<release> GitHub Release (orphanet.sqlite.gz). Local development can fetch that
artifact, verify its sha256, and fall back to a local build; production's init sidecar verifies the
declared immutable digest and the app only reads the resulting snapshot. make data-status prints
the loaded release. Details: Data & the build pipeline.
Runtime data identity — a pinned deployment proves which data release it is serving. The init
sidecar records the release tag and digests in data-identity.json beside the database; /health
rehashes the database on every call and publishes data_available plus a release_identity
{expected, actual} pair, answering 503 if they differ. python -m orphanet_link.data_probe
prints a deterministic read-only {data_schema_version, record_count, query_result_sha256}
observation of the live store. Details:
Runtime data identity.
Licence — Orphadata are CC BY 4.0. Redistributing a derived SQLite database is explicitly permitted provided attribution is given and changes are indicated.
Required citation — also served by the orphanet://citation resource:
"Orphadata Science: Free access data from Orphanet. © INSERM 1999. Available on http://sciences.orphadata.com/. Data version [date/version]." Changes: "Converted Orphadata XML to a normalized SQLite database."
This derived database is not an official Orphanet product and has not been validated by Orphanet or INSERM.
Documentation
Data & the build pipeline — the eight Orphadata products, the data CLI, licensing, and the CI artifact pipeline.
Deployment — transports (and the
--transport httpfootgun), Docker, the Host/Origin/CORS boundary, router integration, deploy verification.Configuration — the
ORPHANET_LINK_*variables;.env.exampleis the exhaustive annotated reference.Architecture & the MCP surface — response envelope, response modes,
orphanet://resources, error taxonomy, and where the research-use warning lives.AGENTS.md— engineering conventions: the two planes, invariants, the determinism contract, package layout.CHANGELOG.md— release history.
Contributing
See AGENTS.md for the conventions and the definition of done. make ci-local is the
gate — format, lint, line budget, README standard, action pins, mypy, and tests — and it must be
green before merge.
License
Code: MIT © 2026 Bernt Popp.
Data: Orphadata is CC BY 4.0 © INSERM 1999 — attribution required and changes indicated, as stated under Data & provenance.
Available Tools
19 toolsfind_diseases_by_geneFind Diseases by GeneARead-onlyIdempotent
Find all Orphanet disorders associated with an HGNC gene symbol. Returns {orpha_code, name} per disorder with pagination. Signature: find_diseases_by_gene(gene_symbol, limit=, offset=, response_mode=).
Inputs: gene_symbol (required), limit, offset, response_mode.
find_diseases_by_phenotypeFind Diseases by PhenotypeARead-onlyIdempotent
Find all Orphanet disorders annotated with an HPO term id. Returns {orpha_code, name} per disorder with pagination. Signature: find_diseases_by_phenotype(hpo_id, limit=, offset=, response_mode=).
Inputs: hpo_id (required), limit, offset, response_mode.
get_diagnosticsGet Orphanet DiagnosticsARead-onlyIdempotent
Report the local Orphanet index status: whether the data is built, the loaded Orphanet release version, disorder counts, schema version, and when it was built, plus a runtime block (request/error counts, latency percentiles p50/p95/p99, a response_mode distribution that surfaces over-fetch, and a version-hash cache hit/miss ratio). Use this to confirm freshness or diagnose a data_unavailable error. Signature: get_diagnostics().
Inputs: no named parameters.
get_diseaseGet DiseaseARead-onlyIdempotent
Return an Orphanet disease record: definition, synonyms, grouped cross-references, classification parents/children, age of onset, inheritance, and disorder type. The term accepts an ORPHAcode, a label/synonym, or an external xref CURIE (resolved first). xrefs are grouped by source; any nested count is leaf rows, not groups. Pass fields=['xrefs.OMIM', ...] for a sparse projection, or include=['genes','phenotypes','prevalence','disability'] to compose a full entity in ONE call. Signature: get_disease(term, response_mode=, fields=, include=).
Inputs: term (required), fields, include, response_mode.
get_disease_ancestorsGet Disease AncestorsARead-onlyIdempotent
Return all transitive ancestors (broader diseases) of an Orphanet disorder via the precomputed closure, with a pagination block {total, returned, limit, offset, truncated, next_offset}. When truncated, next_commands carries a forward-page step. Use get_disease_classification for only the immediate parents. Signature: get_disease_ancestors(term, limit=, offset=, response_mode=).
Inputs: term (required), limit, offset, response_mode.
get_disease_batchGet Diseases (batch)ARead-onlyIdempotent
Fetch many disease records in one call (partial success per item: each row is the record or its own ok=false/error_code/message). Each term accepts an ORPHAcode, label, or xref CURIE; pass fields=[...] for a sparse projection. Max 50 items; compact per item. Signature: get_disease_batch(terms, response_mode=, fields=).
Inputs: terms (required), fields, response_mode.
get_disease_classificationGet Disease ClassificationARead-onlyIdempotent
Return the immediate Orphanet classification parents and children for a disorder. Use get_disease_ancestors / get_disease_descendants for the transitive closure. Signature: get_disease_classification(term, response_mode=).
Inputs: term (required), response_mode.
get_disease_descendantsGet Disease DescendantsARead-onlyIdempotent
Return all transitive descendants (more specific diseases) of an Orphanet disorder via the precomputed closure, with a pagination block {total, returned, limit, offset, truncated, next_offset}. When truncated, next_commands carries a forward-page step. Use get_disease_classification for only the immediate children. Signature: get_disease_descendants(term, limit=, offset=, response_mode=).
Inputs: term (required), limit, offset, response_mode.
get_disease_disabilityGet Disease DisabilityARead-onlyIdempotent
Return functional consequence (disability) data for an Orphanet disorder: ability categories affected and severity grades. Data coverage is partial: many disorders carry no Orphadata functional-consequence annotation, so a valid result can be empty -- coverage:'none' with count:0 marks this explicitly (it is NOT an error); coverage:'present' means rows exist. Signature: get_disease_disability(term, response_mode=).
Inputs: term (required), response_mode.
get_disease_genesGet Disease GenesARead-onlyIdempotent
Return gene-disease associations for an Orphanet disorder: gene symbol, HGNC id, association type, and cross-references (OMIM, Ensembl, etc.). count is the number of leaf gene rows, not grouped associations. Signature: get_disease_genes(term, response_mode=).
Inputs: term (required), response_mode.
get_disease_natural_historyGet Disease Natural HistoryARead-onlyIdempotent
Return natural history data for an Orphanet disorder: age of onset categories and inheritance patterns. Signature: get_disease_natural_history(term, response_mode=).
Inputs: term (required), response_mode.
get_disease_phenotypesGet Disease PhenotypesARead-onlyIdempotent
Return HPO phenotype annotations for an Orphanet disorder: HPO id, term name, and frequency category. Optionally filter by frequency label. Frequency values: Obligate (100%), Very frequent (99-80%), Frequent (79-30%), Occasional (29-5%) (and others). Signature: get_disease_phenotypes(term, frequency=, response_mode=).
Inputs: term (required), frequency, response_mode.
get_disease_prevalenceGet Disease PrevalenceARead-onlyIdempotent
Return prevalence data for an Orphanet disorder: prevalence class, geographic area, and source reference. Signature: get_disease_prevalence(term, response_mode=).
Inputs: term (required), response_mode.
get_server_capabilitiesGet Server CapabilitiesARead-onlyIdempotent
Return the orphanet-link discovery surface: identity/build/Orphanet release, the tool list WITH call signatures, response modes, recommended workflows, the cross-reference source ranking, the error taxonomy, and limits. detail='full' adds the full policy notes. Call this first in a cold session, or read orphanet://tools / orphanet://capabilities. Signature: get_server_capabilities(detail=).
Inputs: detail.
map_cross_ontologyMap Cross-OntologyARead-onlyIdempotent
List an Orphanet disorder's cross-references to other ontologies, grouped by source (OMIM/MONDO/ICD-10/ICD-11/UMLS/GARD/MeSH/MedDRA), each with its mapping relation. Returns them under mappings (get_disease returns the same data under xrefs). Use prefixes=['OMIM'] to restrict to a subset of sources. count is the number of leaf mapping rows (individual targets), not the number of source groups. Signature: map_cross_ontology(term, prefixes=, response_mode=).
Inputs: term (required), prefixes, response_mode.
resolve_diseaseResolve DiseaseARead-onlyIdempotent
Resolve a disease label, synonym, or ORPHAcode (ORPHA:166024 or 166024) to the canonical Orphanet term {orpha_code, name, match_type}. An ambiguous label returns ambiguous_query with candidates. Signature: resolve_disease(query, response_mode=).
Inputs: query (required), response_mode.
resolve_disease_batchResolve Diseases (batch)ARead-onlyIdempotent
Resolve many labels/ORPHAcodes/xrefs in one call (partial success: each item returns its resolution {orpha_code, name, match_type} or its own ok=false/error_code/message; the call never fails wholesale). Max 50 items; compact per item. Signature: resolve_disease_batch(queries, response_mode=).
Inputs: queries (required), response_mode.
resolve_xrefResolve Cross-ReferenceARead-onlyIdempotent
Resolve an external cross-reference CURIE (OMIM/MONDO/ICD-10/ICD-11/UMLS/GARD/MeSH/MedDRA) back to the Orphanet disorder(s) that map to it. Returns matches[] plus a pagination block {total, returned, limit, offset, truncated, next_offset}; when truncated, next_commands carries a forward-page step. Miss semantics (list-shaped, unlike resolve_disease): a malformed CURIE is rejected with invalid_input, while a well-formed but unmapped CURIE returns an empty page (total: 0), not not_found. Signature: resolve_xref(xref_id, limit=, offset=, response_mode=).
Inputs: xref_id (required), limit, offset, response_mode.
search_diseasesSearch DiseasesARead-onlyIdempotent
Full-text search over Orphanet disease names, synonyms, and definitions (FTS, relevance-ranked). Returns {orpha_code, name, score} plus a pagination block {total, returned, limit, offset, truncated, next_offset}. When truncated, next_commands carries a forward-page step. Obsolete terms are excluded unless include_obsolete=true. Signature: search_diseases(query, limit=, offset=, include_obsolete=, response_mode=).
Inputs: query (required), limit, offset, response_mode, +1 more.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 19 tools
Most tools map to clearly distinct data facets, but get_disease can return xrefs, natural history, and other fields that have dedicated tools, and map_cross_ontology overlaps with get_disease's xrefs. The overlap is documented in descriptions, so an agent can still disambiguate, but it is not always obvious which tool is primary.
Tool names follow a consistent snake_case verb_noun pattern: get_disease_*, resolve_*, find_diseases_by_*, search_diseases, and batch variants extend the same pattern predictably. This makes the toolset easy to navigate and guess.
19 tools is on the heavy side for an MCP server, and some redundancy exists: get_disease can compose several facets that also have dedicated tools, and resolve_disease_batch/get_disease_batch add convenience but also surface area. The count is defensible for the breadth of Orphanet data, but feels slightly over-scoped.
The toolset covers the core Orphanet domain thoroughly: disease resolution and search, full disease records with genes/phenotypes/prevalence/natual-history/disability, reverse lookups by gene and phenotype, classification closure, external cross-reference mapping in both directions, and batch operations. There are no obvious dead ends or missing critical operations for a read-only data server.
Maintenance
Related MCP Connectors
MCP gateway federating 22 biomedical MCP servers behind one endpoint: gnomAD, ClinVar, HPO, VEP.
MyDisease.info MCP. Aggregated disease annotation from the BioThings ecosystem: MONDO/DOID/OMIM…
Auditable MCP server for PubMed, Europe PMC, ClinicalTrials.gov, and bioRxiv/medRxiv queries
MCP server for US nursing facility search and ownership lookup (NursingHomeDatabase).
Related MCP Servers
- AlicenseAqualityBmaintenanceMCP server that provides tools to query harmonized gene-disease validity data from the Gene Curation Coalition, supporting consensus and conflict detection for gene-disease assertions.12MIT
- AlicenseAqualityBmaintenanceMCP server that provides tools for querying the Human Phenotype Ontology (HPO) including term lookup, hierarchy exploration, cross-ontology mappings, and gene-phenotype-disease associations, all grounded in a local SQLite database for fast offline lookups.171MIT
- AlicenseAqualityDmaintenanceAn MCP server for searching and accessing RNA sequencing datasets from the European Nucleotide Archive (ENA), supporting bulk, single-cell, and spatial transcriptomics with advanced filtering and download capabilities.111,843 PyPI1Apache 2.0
- AlicenseAqualityFmaintenanceMCP server for Brazilian ICD-10 (CID-10) that enables search, lookup, hierarchy navigation, statistics, and validation of disease codes from official DATASUS data.6339 npm1MIT