Skip to main content
Glama

bioretrieval-mcp

An MCP server that gives LLM agents typed access to cryo-EM, protein, and DNA-methylation research tools: EMDB search, UniProt lookups, ESM-2 embeddings, sequence-to-cryo-EM-map retrieval with a trained two-tower model, and GEO methylation-array search. It comes with a 40-question eval run with Claude as the MCP client.

demo

Tools

Tool

What it does

Backend

search_emdb(query, resolution_max?, limit?)

Keyword or Solr search over EMDB; returns resolution, method, organisms, fitted PDBs, UniProt xrefs, Pfam, microscope, citation

EBI EMDB API

get_uniprot(accession)

Sequence, curated function, Pfam families, genes, organism, review status, EMDB xrefs

UniProt REST

embed_sequence(sequence, include_vector?)

ESM-2 650M (esm2_t33_650M_UR50D) final-layer mean-pooled 1280-d embedding, cached on disk

local, torch

retrieve_maps(sequence, k?)

Top-k cryo-EM maps for a protein sequence from the two-tower retrieval model, with cosine scores

local, torch

search_geo_methylation(query, platform)

GEO series on 27K / 450K / EPIC / EPICv2 arrays, with sample counts, dates, PubMed IDs

NCBI E-utilities

cpgpt_embed(sample_id) (optional)

Precomputed CpGPT sample embedding, registered only when an embedding store is configured

local

Every tool has a typed JSON input schema (ranges, enums, required fields) and a typed outputSchema, so clients get structuredContent as well as text. Tools are annotated read-only/idempotent.

Platform to GPL mapping used by search_geo_methylation (checked against the GEO platform records): 27K = GPL8490; 450K = GPL13534, GPL16304; EPIC = GPL21145, GPL23976; EPICv2 = GPL33022.

Related MCP server: BioLab MCP Server

Quick start

uv venv && uv pip install -e ".[ml,dev]"      # drop [ml] for the API-only tools

# stdio (Claude Desktop / Claude Code / any MCP client)
bioretrieval-mcp

# streamable HTTP
bioretrieval-mcp --transport streamable-http --port 8000   # served at http://127.0.0.1:8000/mcp

Claude Code: claude mcp add bioretrieval -- /path/to/.venv/bin/bioretrieval-mcp

Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "bioretrieval": {
      "command": "/path/to/.venv/bin/bioretrieval-mcp",
      "env": {
        "BIORETRIEVAL_MAP_INDEX": "/path/to/map_index.npz",
        "BIORETRIEVAL_RETRIEVAL_CHECKPOINT": "/path/to/best.pt"
      }
    }
  }
}

Docker:

docker build -t bioretrieval-mcp .                    # API tools only
docker build --target ml -t bioretrieval-mcp:ml .     # + ESM-2 / retrieval (CPU torch)
docker run -p 8000:8000 -v bioretrieval-data:/data bioretrieval-mcp

Configuration

Env var

Default

Purpose

BIORETRIEVAL_CACHE_DIR

~/.cache/bioretrieval-mcp

HTTP response cache (SQLite) and ESM embedding cache

BIORETRIEVAL_HTTP_TIMEOUT_S

20

Per-request timeout

BIORETRIEVAL_HTTP_MAX_RETRIES

3

Retries on timeouts, connection errors, 408/425/429/5xx

BIORETRIEVAL_HTTP_CACHE_TTL_S

86400

Response cache TTL

BIORETRIEVAL_MAP_INDEX

unset

Map index .npz; enables retrieve_maps

BIORETRIEVAL_RETRIEVAL_CHECKPOINT

unset

Two-tower checkpoint (sequence tower)

BIORETRIEVAL_CPGPT_EMBEDDINGS

unset

CpGPT embedding store; enables cpgpt_embed

BIORETRIEVAL_DEVICE

auto

cuda / mps / cpu

NCBI_API_KEY, BIORETRIEVAL_NCBI_EMAIL

unset

NCBI identification; the key raises the rate limit from 3 to 10 req/s

Retrieval model

retrieve_maps serves the sequence tower of the multimodal model from the companion paper (ESM-2 650M sequence encoder, 3D-CNN volume encoder, shared 512-d latent space, trained with JEPA prediction + symmetric InfoNCE + VICReg on human EMDB maps). Only the sequence tower runs at query time; map embeddings are computed offline by the volume tower and shipped as an index:

# 1. on the GPU box: encode every map with the volume tower -> map_emb.npy (N x 512), rows = metadata order
# 2. package it
python scripts/build_map_index.py two-tower --embeddings map_emb.npy \
    --metadata metadata_curated.csv --model "JEPA+InfoNCE two-tower" --out map_index.npz --fetch-titles
# 3. serve
BIORETRIEVAL_MAP_INDEX=map_index.npz BIORETRIEVAL_RETRIEVAL_CHECKPOINT=best.pt bioretrieval-mcp

The checkpoint loader autodetects both trainer formats in the research repo (mmprotein trainer: model_state_dict / seq_projector; end-to-end trainers: model / sequence_projection, including fine-tuned ESM-2 weights when present) and rebuilds the projection head from the weight shapes.

Without a checkpoint, build_map_index.py esm-baseline builds an index where each map is represented by the ESM-2 embedding of its paired UniProt sequence. Retrieval then reduces to sequence nearest-neighbour search. The tool reports which model produced each result, so agents and users can tell them apart.

Engineering

  • Transports: stdio and streamable HTTP (both exercised in the test suite with a real server subprocess).

  • Caching: SQLite TTL cache for upstream responses; ESM embeddings cached on disk by sequence hash (cold 183-residue embedding about 7 s on Apple M-series including model load; cache hits return immediately).

  • Resilience: per-request timeouts, exponential backoff with jitter, Retry-After support, per-host pacing for NCBI's rate limit. Upstream failures come back as MCP tool errors (isError: true) with an agent-readable message instead of crashing the session.

  • Validation: UniProt accession regex, amino-acid alphabet and length checks (DNA input is rejected with a hint), Solr query sanitisation, bounded k / limit / resolution_max, enum-typed platforms. Invalid input is rejected before any network call.

  • Tests: 89 pytest tests, all upstream APIs mocked with httpx.MockTransport and recorded fixtures. The GitHub Actions workflow runs them on Python 3.10/3.12/3.13 and adds a Docker build + HTTP smoke test.

pytest                 # offline, a few seconds

Evaluation

40 research questions (eval/questions.jsonl) across UniProt (10), EMDB (9), GEO methylation (9), embeddings (3), retrieval (5), and multi-tool chains (4). Each has a gold answer, deterministic key-fact checks, and the tool calls that ground it. eval/verify_gold.py re-runs those calls against the live sources and confirms every gold fact is present in current tool output, so no gold answer depends on model memory.

Claude (claude-opus-5-5) is the MCP client: it sees exactly the tool list the server advertises and every call goes over a real stdio MCP session.

Metric

Definition

Tool-selection accuracy

All tools required by the question were called (also: first-call accuracy, call precision)

Answer correctness

Claude judge vs gold answer (correct / partially_correct / incorrect); plus deterministic key-fact checks

Faithfulness

Ragas definition: answer split into atomic claims, each checked for support in the context the agent had (the tool descriptions it was shown plus the tool outputs it received); supported / total

python eval/verify_gold.py                       # ground-truth check, no LLM
python eval/run_eval.py --out eval/results/run.jsonl
python eval/score.py eval/results/run.jsonl      # writes run.scores.json and run.summary.md

Results

Agent claude-opus-5-5 (effort medium), grader claude-opus-5-5, gold snapshot 2026-10-21, one run. retrieve_maps used the ESM-2 baseline index, not the trained two-tower model (see below).

slice

n

tool selection

first call

call precision

key facts

judge correct

correct or partial

faithfulness

all

40

100.0%

100.0%

100.0%

100.0%

100.0%

100.0%

0.912

uniprot

10

100.0%

100.0%

100.0%

100.0%

100.0%

100.0%

0.873

emdb

9

100.0%

100.0%

100.0%

100.0%

100.0%

100.0%

0.949

geo

9

100.0%

100.0%

100.0%

100.0%

100.0%

100.0%

0.923

embed

3

100.0%

100.0%

100.0%

100.0%

100.0%

100.0%

0.832

retrieval

5

100.0%

100.0%

100.0%

100.0%

100.0%

100.0%

0.929

multi

4

100.0%

100.0%

100.0%

100.0%

100.0%

100.0%

0.944

60 tool calls in total (1.5 per question), 1 tool error (q10's deliberate lookup of a nonexistent accession, which the agent reported correctly). Median latency 8.8 s per question, p90 16.4 s. One of 120 grading calls was declined by a safety classifier and re-run on claude-opus-5 via server-side fallback.

What the numbers say, and what they don't.

  • Faithfulness is the informative metric here, and 0.912 is conservative. 72 of 1,021 answer claims (7.1%) were marked unsupported. They fall into two groups:

    • Background knowledge the agent added despite being told to ground every statement: protein biology (preproinsulin structure, mTOR domain positions) and general advice ("UniProt sometimes merges accessions", q10 at 0.33).

    • Grader false negatives. 44 of the 72 contain accessions, and every one of those accessions appears in the tool output the agent received. Spot checks (q15, q20, q33, q36, q37) confirmed the stated facts were in the output, so the true faithfulness is higher. The score is reported as graded, without heuristic correction.

  • Tool selection and correctness are at ceiling, so this set does not separate good from great. Most questions need one or two tool calls with clear routing cues. A harder set (ambiguous routing, longer chains, questions that should be refused or need clarification) is the obvious next step.

  • Retrieval questions mostly test plumbing. With the baseline index, a query whose exact sequence is in the index scores 1.0 against its own maps, so these 5 questions check that the agent chains UniProt to retrieval correctly, not that the trained model retrieves well. Retrieval quality is reported in the paper (median rank 2 to 3 over 3,275 maps).

  • Grader and agent are the same model, which can bias grading in the agent's favour. The deterministic key-fact checks (100%) do not depend on the grader and agree with it.

Eval corrections after the first run (disclosed). The first scoring pass gave 97.5% tool selection, 95.0% judge-correct and 0.905 faithfulness (eval/results/run.v1.summary.md). Reviewing the misses showed three problems with the eval, not the agent, which are fixed in questions.jsonl (see each item's gold_note):

  1. q22: the gold answer counted all 11 GEO hits as ovarian-cancer studies. The agent correctly excluded a cholangiocarcinoma series (GSE38860) and a SuperSeries duplicate, reporting 9.

  2. q26: the gold answer treated every EPICv2 "placenta" hit as placental. The agent correctly identified a macrophage study and a twins study as off-topic.

  3. q31: the question is answerable from embed_sequence's advertised description (1,022-residue limit), so calling that tool became optional. Faithfulness now also counts tool descriptions as context, since the agent legitimately reads them.

The agent was not re-run; only the grading changed. The eval also surfaced a product fix: in q31 the agent had to guess which 1,022 residues embed_sequence keeps. The embed_sequence and retrieve_maps descriptions now state that the first 1,022 are kept (fixed after this run, so the run above used the old wording).

Layout

src/bioretrieval_mcp/
  server.py          tool definitions, transports, entry point
  http.py cache.py   retrying cached HTTP client
  validation.py      input validation
  schemas.py         typed tool outputs
  sources/           emdb.py, uniprot.py, geo.py
  ml/                esm.py (ESM-2 + cache), retrieval.py (two-tower), cpgpt.py
scripts/             build_map_index.py, export_cpgpt_embeddings.py
eval/                questions.jsonl, run_eval.py, score.py, verify_gold.py, demo.py
tests/               pytest suite + recorded API fixtures

Available Tools

3 tools
get_uniprotGet UniProt entryA
Read-onlyIdempotent

Fetch a UniProtKB entry: amino-acid sequence, curated function, Pfam families, gene names, organism, review status, and EMDB cross-references.

NameRequiredDescriptionDefault
accessionYesUniProtKB accession, e.g. P02794 or P0DTC2.

Output Schema

NameRequiredDescription
urlYes
pfamYes
genesYes
lengthYes
functionYesUniProt 'FUNCTION' comment, if curated
organismYes
reviewedYes
sequenceYes
taxon_idYes
accessionYes
entry_nameYes
protein_nameYes
emdb_cross_refsYesEMDB entries cross-referenced by UniProt

TDQS

A3.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint and openWorldHint, so the safety profile is fully covered and the description isn't required to restate it. What the description adds is content scope — the specific categories of data returned — which helps the agent judge relevance, but it says nothing about not-found handling, format, or rate/access constraints.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

One sentence, front-loaded with the action and resource, with the field enumeration following as supporting detail. Nothing is padded and nothing could be cut without losing information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With one documented parameter, a full output schema, and complete annotations, an agent has everything needed to call this correctly. The only gap is behavior on an invalid or nonexistent accession, which is a minor omission given the otherwise rich structured metadata.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There is only one parameter and schema description coverage is 100%, including concrete example accessions (P02794, P0DTC2). The description adds no further semantics, so the baseline 3 applies — the schema does all the work.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Fetch') and resource ('a UniProtKB entry') and then enumerates the payload the agent will get back (sequence, function, Pfam families, gene names, organism, review status, EMDB cross-references). The sibling tools (search_emdb, search_geo_methylation) are unrelated retrieval tools, so no differentiation is needed and none is confused.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The single required 'accession' parameter plus 'Fetch a UniProtKB entry' makes the usage pattern (lookup by identifier) obvious, but there is no explicit statement of when to reach for this versus a search tool, and no note about what happens for an unknown accession. Usage is implied rather than stated.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_emdbSearch EMDBA
Read-onlyIdempotent

Search the Electron Microscopy Data Bank for cryo-EM entries.

Returns per-entry metadata: title, resolution (Ã…), method, source organisms, fitted PDB models, UniProt cross-references, Pfam names, microscope, release date and primary citation. Results are relevance-ranked by EMDB.

NameRequiredDescriptionDefault
limitNoMaximum entries to return.
queryYesKeywords or EMDB Solr syntax, e.g. 'apoferritin', 'spike AND Homo sapiens', 'fitted_pdbs:7a6a', 'xref_UNIPROTKB:P02794'.
resolution_maxNoOnly return maps at or better than this resolution (Ã…).

Output Schema

NameRequiredDescription
queryYesExact Solr query sent to EMDB
entriesYes
returnedYes

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint, idempotentHint and openWorldHint, so safety is covered; the description adds genuine value by disclosing what is returned (resolution, fitted PDBs, UniProt/Pfam cross-refs) and that ranking is relevance-based with no sort control exposed. It does not mention result capping/pagination behavior, but the annotations carry most of the safety burden.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with the core action and scope. The second sentence enumerates return fields, which is somewhat redundant given a dedicated output schema exists, but it is compact and skimmable rather than padded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema, full parameter documentation and read-only/idempotent annotations, the description only needs to establish purpose and result character, which it does. The main remaining gap is the absence of any guidance tying this search to the sibling get_uniprot tool for cross-reference workflows.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100% — query examples, limit bounds and resolution_max semantics are all fully documented in the schema — so the baseline of 3 applies. The description mentions resolution in the return payload, which loosely connects to resolution_max, but adds no filtering syntax or format detail beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb and resource ('Search the Electron Microscopy Data Bank for cryo-EM entries'), which is unambiguous and immediately separates it from the unrelated siblings get_uniprot and search_geo_methylation. It stops short of explicitly naming a sibling or boundary, but the domain is so distinct that confusion is unlikely.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is only implied by the resource domain — an agent infers to call it when it wants cryo-EM map entries. There is no explicit when-to-use/when-not guidance, no mention of how it relates to get_uniprot (e.g., for cross-referenced protein data), and no hint about when to prefer structured Solr syntax versus a plain keyword query.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

search_geo_methylationSearch GEO methylation seriesA
Read-onlyIdempotent

Search NCBI GEO for DNA-methylation series (GSE) run on a given Illumina array.

Returns total hit count plus, per series: accession, title, summary (truncated), platforms, sample count, organisms, submission date and linked PubMed IDs.

NameRequiredDescriptionDefault
limitNoMaximum series to return.
queryYesFree-text GEO query, e.g. 'Alzheimer brain', 'aging blood', 'colorectal cancer'.
platformYesIllumina array: 27K (GPL8490), 450K (GPL13534), EPIC (GPL21145), EPICv2 (GPL33022).

Output Schema

NameRequiredDescription
queryYes
seriesYes
platformYes
returnedYes
total_countYesTotal matching series in GEO (results are paged)
platform_gplsYes

TDQS

A4/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnly, idempotent and openWorld, so the safety profile is covered. The description adds genuine behavioral detail beyond that: it returns a total hit count and flags that summaries are truncated — a real caveat an agent should know when consuming results.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, zero waste. The action and scope come first, followed by the return payload, which is the correct front-loading for a search tool.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With an output schema present and full parameter documentation, the description only needs to frame scope and caveats, which it does. Minor gaps remain: no mention of result ordering or whether 'limit' paginates or merely truncates the hit set.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so all three parameters (limit, query, platform with GPL mappings) are already documented in the schema. The description only restates the 'given Illumina array' constraint and adds no syntax, default, or result-ordering detail beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Search NCBI GEO for DNA-methylation series (GSE)') plus a scoping constraint ('run on a given Illumina array'). Sibling tools (search_emdb, get_uniprot) are in entirely different domains, so no confusion is possible.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The domain context ('DNA-methylation series on an Illumina array') implies appropriate usage, but there is no explicit when-to-use guidance, no exclusions, and no mention of alternatives for e.g. non-methylation or non-array GEO records.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 3 tool updatesv0.1.0
    • First observedget_uniprot
    • First observedsearch_emdb
    • First observedsearch_geo_methylation

TDQS

A4/5.0

Scored across 3 tools

Disambiguation5/5

Each tool targets a clearly different resource and action: EMDB search, UniProt entry retrieval, and GEO methylation series search. There is no realistic overlap in selection, even though EMDB results may contain UniProt cross-references.

Naming Consistency5/5

All tools use consistent snake_case verb_noun naming: search_emdb, get_uniprot, search_geo_methylation. The mix of search and get reflects the intended action rather than inconsistent conventions.

Tool Count5/5

Three tools is well within a focused retrieval server’s scope, and each covers a distinct biological data source. None appears redundant or gratuitous.

Completeness3/5

Coverage is uneven: UniProt has fetch but no search, while EMDB and GEO methylation have search but no dedicated full-entry retrieval beyond returned metadata. These are notable gaps for common retrieval workflows, though partial workarounds exist via cross-references and search metadata.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    A
    quality
    A
    maintenance
    A high-performance MCP server that gives LLMs access to 25 biomedical tools federated across 50+ upstream APIs for genes, variants, drugs, diseases, literature, clinical trials, and structural biology.
    42
    352 npm
    12
    Apache 2.0
  • A
    license
    Not graded
    quality
    C
    maintenance
    MCP-native scientific skills for reproducible computational biology and AI-driven drug-discovery workflows. It combines deterministic scientific tools with an MCP server to give AI agents real computational capabilities.
    Apache 2.0