An MCP (Model Context Protocol) server for mapping biomedical text to standardized ontology terms.
annotate_ontology_terms— Map specific terms to ontology IDs via a multi-stage pipeline:- Exact label match (OLS)
- Synonym match (OLS)
- Fuzzy search (OLS)
- BioPortal fallback (optional, requires API key)
extract_and_annotate— Extract biomedical entities from free text using Claude, then annotate each entity.- Supports domains:
disease,chemical,gene,phenotype,anatomy,organism - Configurable default ontologies per domain
- Retry with exponential back-off on API failures
- Python 3.10+
- uv for dependency management
# Clone the repo
git clone <repo-url>
cd mcp-ontology-annotator
# Create and activate virtual environment with uv
uv venv
source .venv/bin/activate # Linux/macOS
# .venv\Scripts\activate # Windows
# Install the package and dependencies
uv pip install -e ".[dev]" # includes dev/test dependencies
# or just the runtime:
uv pip install -e .Copy .env.example to .env and fill in values:
cp .env.example .env| Variable | Default | Required |
|---|---|---|
ANTHROPIC_API_KEY |
— | For extract_and_annotate |
OLS_API_URL |
https://www.ebi.ac.uk/ols4/api |
No |
BIOPORTAL_API_KEY |
— | For BioPortal fallback |
BIOPORTAL_API_URL |
https://data.bioontology.org |
No |
DEFAULT_DISEASE_ONTOLOGIES |
mondo,doid,hp |
No |
DEFAULT_CHEMICAL_ONTOLOGIES |
chebi,drugbank |
No |
DEFAULT_GENE_ONTOLOGIES |
hgnc,ncbigene |
No |
DEFAULT_PHENOTYPE_ONTOLOGIES |
hp,mp |
No |
DEFAULT_ANATOMY_ONTOLOGIES |
uberon,fma |
No |
DEFAULT_ORGANISM_ONTOLOGIES |
ncbitaxon |
No |
# After installing with uv pip install -e .
ontology-annotator
# or
python -m ontology_annotator.serverThe server communicates over stdio, as required by the MCP protocol.
Add to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS):
{
"mcpServers": {
"ontology-annotator": {
"command": "uv",
"args": [
"run",
"--directory", "/path/to/ontology-annotator-mcp",
"ontology-annotator"
],
"env": {
"ANTHROPIC_API_KEY": "sk-ant-...",
"BIOPORTAL_API_KEY": ""
}
}
}
}pytestruff check src tests
ruff format src testspython examples/example_usage.py| Parameter | Type | Default | Description |
|---|---|---|---|
texts |
string | string[] |
required | Term(s) to annotate |
domain |
string |
— | Biomedical domain (narrows ontology search) |
preferred_ontologies |
string[] |
— | Override default ontologies |
use_bioportal_fallback |
boolean |
true |
Fall back to BioPortal |
min_confidence |
number |
0.7 |
Minimum confidence (0–1) |
| Parameter | Type | Default | Description |
|---|---|---|---|
text |
string |
required | Natural language text |
domains |
string[] |
all | Entity types to extract |
preferred_ontologies |
object |
— | Per-domain ontology preferences |
use_bioportal_fallback |
boolean |
true |
Fall back to BioPortal |
min_confidence |
number |
0.7 |
Minimum confidence |
ontology-annotator-mcp/
├── src/
│ └── ontology_annotator/
│ ├── __init__.py
│ ├── server.py # MCP server
│ ├── annotator.py # Multi-stage annotation pipeline
│ ├── extractor.py # LLM entity extraction
│ ├── ols_client.py # OLS4 API client
│ ├── bioportal_client.py # BioPortal API client (optional)
│ └── config.py # Settings via env vars
├── tests/
│ └── test_annotator.py
├── examples/
│ └── example_usage.py
├── pyproject.toml
├── .env.example
└── README.md
Follow these steps to release a new tagged version in the repo and to update PyPI.
# 1. Update version in pyproject.toml
# version = "0.1.1" or "0.2.0"
# 2. Commit changes
git commit -am "Version 0.1.1: Add improvements"
# 3. Tag the release
git tag v0.1.1
git push && git push --tags
# 4. Clean old builds
rm -rf dist/
# 5. Build new version
python -m build
# 6. Upload to the official PyPI site
twine upload dist/*