TogoMCP
TogoMCP lets an AI assistant query dozens of life-science databases through one MCP server — SPARQL against RDF Portal knowledge graphs plus a set of REST API wrappers — with built-in schema guidance (MIE files) and ID-conversion tools to join them up.
Guided SPARQL over RDF databases —
run_sparqlagainst ~37 registered databases (UniProt, PDB, ChEMBL, ChEBI, PubChem, Reactome, Rhea, Ensembl, NCBI Gene, ClinVar, MedGen, MeSH, GO, MONDO, PubMed, PubTator, BacDive, MediaDive, GlyCosmos, Bgee, OMA, BRENDA, HGNC, jPOST, MassBank, NBRC, GWAS Catalog, TogoVar, etc.), including cross-database queries on shared endpoints.Schema/endpoint discovery —
get_MIE_file(ShEx schema + RDF/SPARQL examples per database),get_sparql_endpoints,get_graph_list(named graphs, so queries can be pinned correctly).Workflow guidance —
TogoMCP_Usage_Guidereturns a step-by-step protocol (classify → plan → pick databases → ground IRIs → read MIE → query) and warns about co-tenancy/pitfalls.Entity resolution / ID lookup —
search_uniprot_entity,search_pdb_entity,search_mesh_descriptor,search_reactome_entity,search_rhea_entity,search_chembl_target/search_chembl_molecule/search_chembl_id_lookup,get_pubchem_compound_id,get_compound_attributes_from_pubchem.Cross-database ID conversion (TogoID) —
togoid_convertId,togoid_countId,togoid_getRelation(s),togoid_getAllDataset,togoid_getDataset,togoid_getDescription(e.g. NCBI Gene ↔ UniProt ↔ PDB ↔ Ensembl ↔ ChEMBL).NCBI E-utilities —
ncbi_esearch,ncbi_esummary,ncbi_efetch,ncbi_list_databasesfor gene, taxonomy, ClinVar, MedGen, MeSH, PubMed, PubChem.Human variant / population-frequency search (TogoVar) —
togovar_search_gene,togovar_search_disease,togovar_search_variant(gnomAD, ToMMo, NCBN, GEM-J, JGA, BBJ frequencies, ClinVar/MGeND significance, SIFT/PolyPhen/AlphaMissense).Reproducible research support — a
record_for_paperprompt/query-provenanceworkflow producing a re-runnable ledger,PROVENANCE.mdandMETHODS.md, plus optional JSONL tool-call logging.Deployment options — hosted remote server, local
uv/stdio install, or Docker/Compose (with optional opt-in KEGG tools on local stdio only).
Provides tools for searching and retrieving biomedical literature from PubMed, including access to citations and abstracts via NCBI E-utilities.
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., "@TogoMCP retrieve the UniProt entry for human p53"
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.
TogoMCP: An MCP Server for Life-Science Databases
An MCP (Model Context Protocol) server that gives AI assistants (Claude, etc.) access to biological and biomedical RDF databases via SPARQL — mostly at the RDF Portal, plus a few databases' own public endpoints (GlyCosmos, TogoVar, WikiPathways, IDSM, LIPID MAPS, SwissLipids, MarpolBase) — as well as selected REST APIs (NCBI E-utilities, UniProt, ChEMBL, PDB, PubChem, Reactome, Rhea, MeSH, TogoID, TogoVar, PubCaseFinder).
Quick Start: Remote Server (No Installation)
You can use the hosted TogoMCP server directly — no local setup needed.
See https://togomcp.rdfportal.org/ for connection instructions.
Related MCP server: mcp-pubmed
Local Installation
Prerequisites
Python >= 3.11
uv package manager
1. Install uv
# macOS/Linux
curl -LsSf https://astral.sh/uv/install.sh | sh
# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"2. Clone and install
git clone https://github.com/dbcls/togomcp.git
cd togomcp
uv sync3. Set NCBI API Key (required for NCBI tools)
Obtain your NCBI API key and export it:
export NCBI_API_KEY="your-key-here"Configuration
Claude Desktop
Edit your Claude Desktop config file:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
~\AppData\Roaming\Claude\claude_desktop_config.json
{
"mcpServers": {
"togomcp": {
"command": "/path/to/uv",
"args": [
"--directory",
"/path/to/togomcp",
"run",
"togo-mcp-local"
],
"env": {
"NCBI_API_KEY": "your-key-here"
}
}
}
}Tip: Run
which uv(macOS/Linux) orwhere uv(Windows) to find the full path touv.
Note on KEGG: TogoMCP does not enable KEGG by default. The
kegg_*tools requireTOGOMCP_ENABLE_KEGG=1and the localstdioserver, because the KEGG API is licensed to academic users at academic institutions. If that is not you, simply leave it unset and everything else works normally. See KEGG (opt-in, localstdioonly).
Docker
A Dockerfile is provided for containerized deployment.
Recommended: docker compose
compose.yaml defines two services — togomcp-main (port 8000) and togomcp-test (port 8001) — so you can run a main and a test endpoint side by side from the same image (for local and development use).
cp .env.example .env # then fill in NCBI_API_KEY
docker build -t localhost/togo-mcp:latest . # build main image (tag in .env)
docker compose up -d togomcp-main # start main endpointCommon operations:
docker compose logs -f togomcp-main # tail logs
docker compose down # stop and remove all services
docker compose down togomcp-test # stop and remove just one
docker compose up -d togomcp-test # after rebuilding, recreates with new imageOverride image tags and host ports via .env — see .env.example for the full list. Use docker compose up -d --force-recreate <svc> if compose doesn't pick up a rebuilt image, and docker image prune -f to clean up dangling layers.
Behind a reverse proxy
Two env vars matter if you put TogoMCP behind nginx/Caddy/Traefik. Both fail in ways that are easy to misdiagnose:
TOGOMCP_ALLOWED_HOSTS— FastMCP validates theHostheader (DNS-rebinding protection) and answers 421 for any host not on the allow-list. The default list is localhost plus the public DBCLS vhosts, so your own hostname must be added or every proxied request is rejected.TOGOMCP_FORWARDED_ALLOW_IPS— which peer addresses may setX-Forwarded-Proto/-For. uvicorn parses those headers but trusts only127.0.0.1unless told otherwise, and a container reached via a published port never arrives as loopback. Left wrong, the header is silently dropped (not rejected): the app then believes it is serving plain HTTP and emits redirects that downgradehttps://tohttp://. The default covers the usual container-runtime ranges; set this only if your proxy sits elsewhere.
Your proxy must also send X-Forwarded-Proto — nginx does not by default (proxy_set_header X-Forwarded-Proto $scheme;), while Caddy and Traefik do. Both halves are required; neither works alone.
Simple: docker run
For a single container without compose:
docker build -t togo-mcp .
docker run -e NCBI_API_KEY="your-key-here" -p 8000:8000 togo-mcpTool-Call Logging (Optional)
TogoMCP can record every MCP tool call as one JSON line per call (timestamp,
tool name, arguments, status, elapsed_ms, session/request/client IDs, transport,
client IP). SPARQL calls are enriched with endpoint URL, HTTP code, row/byte
counts, and a SHA-256 of the query. Note the client IP is the peer address as
the app sees it — behind a proxy or container that is the proxy/gateway, the same
value for every caller, unless TOGOMCP_FORWARDED_ALLOW_IPS lets uvicorn trust
X-Forwarded-For. Useful for benchmarking, MIE iteration,
and reconstructing multi-tool sequences.
The IP is recorded as a salted hash (ip_hash) by default. Set
TOGOMCP_LOG_RAW_IP=1 to also record it in the clear as ip, which is what
lets an abusive caller be identified and blocked — at the cost of making the log
personal data (and /stats/log serves it verbatim to whoever holds the dashboard
credentials). Full field-by-field reference, including the privacy model, is in
log_file_specs.md.
On/off is a single env var: TOGOMCP_QUERY_LOG. Unset/empty = disabled
(zero-overhead default). Set to a writable file path to enable.
Output uses RotatingFileHandler (50 MB × 10, ~500 MB cap).
Docker
compose.yaml bind-mounts ./logs (and ./logs-test) on the host to
/var/log/togomcp inside each container and passes through TOGOMCP_QUERY_LOG
/ TOGOMCP_QUERY_LOG_TEST from .env. Opt in:
echo 'TOGOMCP_QUERY_LOG=/var/log/togomcp/togomcp.jsonl' >> .env
mkdir -p logs
docker compose up -d togomcp-main
tail -f logs/togomcp.jsonlThe path in the env var is the container-side path; the bind mount makes
the same file visible at ./logs/togomcp.jsonl on your host. Leaving the var
unset keeps logging off — no compose changes needed.
Claude Desktop (local stdio)
Add TOGOMCP_QUERY_LOG to the env block alongside NCBI_API_KEY. Use an
absolute path (the spawned process's cwd is unpredictable) and ensure the
parent directory exists:
"env": {
"NCBI_API_KEY": "your-key-here",
"TOGOMCP_QUERY_LOG": "/Users/you/togomcp-logs/togomcp.jsonl"
}Then mkdir -p ~/togomcp-logs once and fully restart Claude Desktop.
Available Databases & Tools
TogoMCP exposes tools for querying the following (via SPARQL or REST APIs):
Category | Resources |
Proteins / Proteomics | UniProt, PDB, jPOST |
Genes / Genomics | NCBI Gene, Ensembl, HGNC, OMA, Bgee, HCO, MCO, DDBJ, MoG+, TogoVar, JoGo, GWAS Catalog, Fanta.bio, TiSMeD, MarpolBase |
Chemistry | ChEMBL, PubChem, ChEBI, Rhea, BRENDA, MassBank, IDSM |
Lipidomics | LIPID MAPS, SwissLipids |
Pathways | Reactome, WikiPathways |
Disease / Clinical | ClinVar, MedGen, MONDO, NANDO, PubCaseFinder |
Literature | PubMed, PubTator |
Microbiology | BacDive, MediaDive, AMR Portal, NBRC |
Glycomics | GlyCosmos |
Ontologies / Vocabulary | MeSH, GO, Ontology Graphs (HP, UBERON, CL, SO, ECO, EFO, PRO, FMA, …) |
Taxonomy | NCBI Taxonomy |
Materials Science | SuperCon |
Identifier conversion | TogoID |
KEGG (opt-in, local stdio only)
KEGG is off by default. You do not need it, and TogoMCP is fully functional without it — this section only matters if you are eligible and want it.
A kegg tool group (kegg_find, kegg_get_entry, kegg_pathway_graph,
kegg_pathway_neighborhood, kegg_pathway_paths, kegg_pathway_cycles,
kegg_link, kegg_conv) is mounted only when both conditions hold:
you run the local
stdioentry pointtogo-mcp-local, andyou set
TOGOMCP_ENABLE_KEGG=1.
Why two gates, for two different reasons:
The transport gate is structural and not configurable. The KEGG API is provided "for academic use by academic users belonging to academic institutions", and offering a service built on KEGG additionally requires an academic service-provider license (see KEGG's terms). A public host cannot verify a caller's affiliation, so the hosted server at togomcp.rdfportal.org — and any HTTP deployment — never reaches
rest.kegg.jp. No environment variable can change this;TOGOMCP_ENABLE_KEGGhas no effect on the HTTP path at all.The opt-in exists because eligibility is yours to assert. Under
stdioyou are the caller, but only you know whether your institution's access covers you. Mounting KEGG by default would put an API call you may not be entitled to make on the path of least resistance — an AI assistant will use any tool it can see. Leaving the variable unset is the correct configuration for a non-academic user, and nothing else is affected.
Enable it in your Claude Desktop config:
"env": {
"NCBI_API_KEY": "your-key-here",
"TOGOMCP_ENABLE_KEGG": "1"
}Calls are capped at 3 requests per second (TogoMCP enforces this process-wide, and
never retries an HTTP 403/429). KEGG is not part of RDF Portal: it has no SPARQL
endpoint, so database="kegg" is invalid in run_sparql. Use kegg_conv to translate
KEGG identifiers to UniProt, NCBI Gene/Protein, ChEBI or PubChem before querying any RDF
database with them.
Example Prompts
Once connected, you can ask your AI assistant things like:
"Find all human proteins associated with Alzheimer's disease in UniProt."
"Run a SPARQL query on the ChEMBL database to find compounds targeting EGFR."
"Search PubMed for recent papers on CRISPR base editing."
"What pathways involve the TP53 gene in Reactome?"
Results for a paper
If you will use the results in a paper, say so at the start of the investigation (e.g. "I will use
this in a paper; record the queries"), or choose the MCP prompt Record this investigation for a
paper (record_for_paper) from your client's prompt menu. The assistant then follows the
query-provenance workflow: it records the exact tool calls behind each finding in a ledger.yaml,
re-runs them to confirm the results, and writes PROVENANCE.md and a draft METHODS.md. Anyone can
re-run a ledger later with scripts/togomcp_reproduce.py, which sends
the SPARQL queries straight to the endpoints:
uv run scripts/togomcp_reproduce.py ledger.yamlSaying it only at the end also works, but in a long conversation the exact text of early queries may no longer be recoverable. Some clients, Claude Desktop among them, do not pass the server's guidance to the model before its first tool call, so they will not start this workflow unless you ask. If the prompt is not in the menu, disconnect and reconnect TogoMCP: clients keep the prompt list from when they first connected.
Directory Structure
togomcp/
├── togo_mcp/ # Main Python package
│ ├── server.py # Root FastMCP instance + tool-call logging middleware
│ ├── main.py # Assembles the server, mounts sub-servers, entry points
│ ├── rdf_portal.py # RDF Portal / SPARQL, MIE, and endpoint tools
│ ├── api_tools.py # REST search wrappers (UniProt, PDB, Reactome, MeSH, PubChem, etc.)
│ ├── chembl.py # ChEMBL REST search wrappers
│ ├── ncbi_tools.py # NCBI E-utilities sub-server
│ ├── togoid.py # TogoID identifier-conversion sub-server
│ ├── togovar.py # TogoVar human-variation sub-server
│ ├── pubcasefinder.py # PubCaseFinder phenotype-ranking / case-report sub-server
│ ├── skills.py # Agent Skills registry (served by get_workflow and as skill:// resources)
│ ├── kegg.py # KEGG sub-server — mounted by togo-mcp-local ONLY (licence, see above)
│ ├── kgml.py # KGML -> signed pathway graph (pure; no network, no FastMCP)
│ ├── stats.py # Tool-call usage-log analysis
│ └── data/ # Bundled data files (included in wheel)
│ ├── mie/ # MIE files (YAML, one per database)
│ ├── docs/ # Developer documentation (MIE spec, examples)
│ ├── resources/ # Static resources (endpoints.csv, usage guide, etc.)
│ └── skills/ # Public Agent Skills (served by get_workflow)
├── benchmark/ # Benchmark question set, scripts, and results
├── scripts/ # Utility/maintenance scripts (deploy, Docker, MIE keywords)
├── tests/ # Pytest test suite
├── tutorial/ # Workshop materials (slides, handbook, hands-on, instructor script)
├── Dockerfile # Docker build configuration
├── compose.yaml # Docker Compose (main + test services)
├── pyproject.toml # Python project metadata and entry points
└── uv.lock # Locked dependency versions (uv)Contributing
Contributions are welcome!
Adding a database: five places, not two. Only the first two affect what the server validates; the rest are documentation surfaces that drift silently, and the tests are what catch them.
togo_mcp/data/resources/endpoints.csv— the registry row (this alone decides validdatabase=values).togo_mcp/data/mie/<db>.yaml— the MIE file (see the MIE spec intogo_mcp/data/docs/).uv run python scripts/generate_usage_guide_catalog.py— regenerates the Usage Guide's database catalog. Guarded bytests/test_catalog_in_sync.py.togo_mcp/data/resources/usage_guide_v7/02_budgets_and_discovery.md— a hand-written copy of the registry that no generator touches. Bump the per-endpoint count and add the key. Guarded byTestUsageGuideEndpointTableintests/test_server.py.togo_mcp/data/docs/togomcp-intro.html— add a card to the database grid (not generated), and the same card totogomcp-intro-ja.html. Guarded bytests/test_trial_pages.py, which requires the two pages to match.
Note that a database removal really is just step 1: nothing validates against the other four.
Adding a tool: pass annotations=READ_ONLY_TOOL to the @mcp.tool decorator. Every TogoMCP tool is read-only, and MCP's default for an unannotated tool is the unsafe one — clients such as ChatGPT treat a tool with no readOnlyHint as a write action, which means a confirmation prompt on every call. A test asserts this, so omitting it fails the build.
Please open an issue or pull request on GitHub.
References
The system paper — describes TogoMCP as a whole (based on MIE v2):
Kinjo, A. R., Yamamoto, Y., Bustamante-Larriet, S., Labra-Gayo, J.-E., & Fujisawa, T. (2026). TogoMCP: Natural Language Querying of Life-Science Knowledge Graphs via Schema-Guided LLMs and the Model Context Protocol. Database 2026:baag042. https://doi.org/10.1093/database/baag042
The MIE v3 report — the ablation study behind the current MIE format. Removing any single MIE section (or any whole functional group) turned out to be statistically null, while removing the MIE entirely cost 0.9 points out of 20 — heavy redundancy, with the query-construction content alone recovering 99% of the total effect. MIE v3 reorganizes around that evidence, matching v2 answer quality at n=100 benchmark questions while using 15% fewer input tokens and running 6% faster:
Kinjo, A. R., & Yamamoto, Y. (2026). Measure before you rewrite: ablation-driven redesign of LLM-facing RDF schema documentation in TogoMCP. BioHackrXiv. https://doi.org/10.37044/osf.io/6v5ra_v1
The measured version of the server is archived as release v2.0.0: https://doi.org/10.5281/zenodo.21543297
License
This project is licensed under the MIT License.
The MIT licence covers this code only, not the data or the third-party APIs it
reaches — each carries its own terms, and you are the caller. Most RDF Portal
databases are open, but note in particular that the KEGG API (kegg_* tools,
opt-in and local stdio only) is licensed to academic users at academic institutions
and requires a separate academic service-provider licence to redistribute as a
service — which is why it is off by default and the hosted server does not expose it at
all. See KEGG (opt-in, local stdio only).
Available Tools
29 toolsget_compound_attributes_from_pubchemARead-only
Get compound attributes from PubChem RDF.
RETURNS the compound attributes as a JSON-formatted string. On upstream/HTTP failure this tool does NOT raise — it returns a plain string beginning with "Error:" (not JSON). CHECK FOR the "Error:" prefix BEFORE parsing.
Inputs: pubchem_compound_id (required). Returns: result
get_graph_listARead-only
Get a list of named graphs on a SPARQL endpoint. ALWAYS pass database (required). Virtuoso/OpenLink internal graphs are filtered out. Graph URIs containing the database substring (case-insensitive) are ranked first — useful when the endpoint hosts multiple databases (e.g. SIB hosts UniProt + Rhea + Bgee + OMA). For a database not yet in the registry, pass endpoint_url (or endpoint_name if its parent endpoint is registered) to bypass database validation; the required database value is then used only as a ranking hint. RETURNS a CSV-formatted list of named graphs (database-name matches first); on missing endpoint selection it returns a string beginning with 'Error:' — check for that prefix before use.
Inputs: database (required), endpoint_url, endpoint_name, include_system. Returns: result
get_MIE_fileARead-only
At the start of any task, identify ALL databases needed and call this tool for EACH of them before writing any SPARQL queries. Do not query a database until its MIE file has been read. Get the MIE (Metadata Interoperability Exchange) file containing the ShEx schema, RDF and SPARQL examples of a specific RDF database. RETURNS the MIE file as a YAML-formatted string; an unknown database returns a string beginning with 'Error:' that lists the valid database names.
Inputs: db, dbname, database. Returns: result
get_pubchem_compound_idARead-only
Get a PubChem compound ID (CID) for a compound name.
RETURNS the PubChem Compound ID(s) as a JSON-formatted string. On upstream/HTTP failure this tool does NOT raise — it returns a plain string beginning with "Error:" (not JSON). CHECK FOR the "Error:" prefix BEFORE parsing.
Inputs: compound_name (required). Returns: result
get_sparql_endpointsARead-only
Get the available SPARQL endpoints for RDF Portal.
RETURNS a dict with two keys: databases (maps each database ->
{url, endpoint_name, keyword_search}) and endpoints (maps each
endpoint_name -> {url, databases}).
Returns: Dict with two keys: - databases: Dict mapping database -> {url, endpoint_name, keyword_search} - endpoints: Dict mapping endpoint_name -> {url, databases}
Inputs: no named parameters. Returns: object
ncbi_efetchARead-only
Fetch full records using efetch. Returns actual data (sequences, records, etc.)
Inputs: db, ids, retmode, rettype, +1 more.
ncbi_esearchARead-only
Search NCBI databases using E-utilities esearch API.
⚠️ CRITICAL FOR COMPREHENSIVE RESULTS ⚠️ ALWAYS use NCBI field tags for Gene, ClinVar, and similar databases! Without field tags, you may miss 70-80% of relevant results.
MANDATORY FIELD TAGS FOR GENE DATABASE: • [Organism] - Taxonomic filtering (e.g., "Homo sapiens[Organism]", "Archaea[Organism]") • [Gene Name] - Gene symbols (e.g., "TP53[Gene Name]", "nifH[Gene Name]") • [All Fields] - Broad keyword search (e.g., "nitrogenase[All Fields]")
IMPACT OF FIELD TAGS (Gene Database): • Without field tags: ~300 results (20-30% recall) ❌ • With field tags: ~1,300 results (100% recall) ✅ • Performance loss: Missing field tags = 70-80% data loss!
EXAMPLE (Gene): ✅ query="Archaea[Organism] AND (nifH[Gene Name] OR nitrogenase[All Fields])" ❌ query="archaea AND nifH" (missing [Organism]/[Gene Name] tags → ~23% recall)
RETURNS formatted text results carrying the database-specific IDs. On a
missing/invalid database or query it returns a single text item whose
message begins with "Error:" — check for that prefix before using the IDs.
Inputs: db, term, query, sort_by, +4 more.
ncbi_esummaryARead-only
Fetch summary information for given IDs using esummary. Useful for getting detailed info after esearch.
RETURNS a text item holding the parsed JSON summary data. On a
missing/invalid database or empty ids it returns a single text item
whose message begins with "Error:" — check for that prefix before use.
Inputs: db, ids, database.
ncbi_list_databasesARead-only
List all supported NCBI databases with descriptions and example queries.
Returns: Formatted list of available databases
Inputs: no named parameters.
run_sparqlARead-only
Run a SPARQL query on an RDF database. ALWAYS pass database (required; valid values: uniprot, rhea, pubchem, pdb, chembl, chebi, reactome, ensembl, amrportal, mesh, go, taxonomy, mondo, nando, bacdive, mediadive, clinvar, pubmed, pubtator, ncbigene, medgen, ddbj, glycosmos, supercon, bgee, oma, brenda, hgnc, jpostdb, massbank, nbrc, mogplus, hco, mco, togovar, ontology, gwascatalog) for single-database queries. For cross-database queries on a shared endpoint, still pass a member database AND add endpoint_name (valid values: sib, pubchem, pdb, ebi, primary, ncbi, ddbj, glycosmos, nims, togovar) or endpoint_url, which take priority over database. Invalid database/endpoint_name values fail immediately with a deterministic error — do not retry. RETURNS the query results as a CSV-formatted string (first row is the header of SELECT variable names).
Inputs: database (required), query, endpoint_url, sparql_query, +1 more. Returns: result
search_chembl_id_lookupARead-only
Resolve a name to ChEMBL IDs across several entity kinds in one call.
Cross-entity convenience wrapper over the ChEMBL RDF graph. Two matching regimes, because the entity kinds carry different searchable text:
• EXACT (case-insensitive) NAME match — COMPOUND (skos:altLabel: brands,
generics, synonyms), TARGET (its own rdfs:label OR its component's
skos:altLabel — gene symbols and protein names), CELL_LINE and TISSUE
(rdfs:label, e.g. "Liver", "CCRF S-180"). Not fuzzy/substring — fix typos
before calling, or use search_chembl_target, which falls back to a
substring pass. Prefer the entity-specific tools
(search_chembl_molecule / search_chembl_target) when you know the kind;
they carry extra fields (organism/type).
• KEYWORD-IN-DESCRIPTION — ASSAY. Assays have no name; their searchable text is a free-text dcterms:description, so ASSAY does a keyword (token) match on that description, NOT an exact match, e.g. entity_type="ASSAY", query="acetylcholinesterase" → every assay whose description mentions it. ASSAY results are relevance-ranked (best description match first).
Default (no entity_type) searches the four EXACT-name kinds and UNIONs them.
ASSAY is opt-in via entity_type="ASSAY" — its keyword semantics and high hit
counts would otherwise swamp a name lookup. (DOCUMENT is not supported; query
SPARQL directly for it.)
The search string can be passed as any of: query (canonical), search,
term, keyword, keywords, search_term, or name.
RETURNS a dict {'total_count', 'has_more', 'results'}. total_count is the
number of rows RETURNED (capped by limit), NOT the full match count; check
has_more (true = more results exist beyond this page — relevant mainly for
ASSAY, whose keyword search can have many hits). ⚠️ On a default (cross-kind)
search, has_more=true can also mean an entire entity_type is missing from
the page: the kinds are UNIONed and the limit is applied to the whole, so
e.g. "Liver" at limit=5 returns 5 TARGET rows and no TISSUE row, though both
exist. Do NOT conclude a kind is absent from a truncated page — raise limit
or re-run with entity_type set. Each result carries
'chembl_id', 'entity_type', and 'organism' (null for COMPOUND / where absent —
use it to tell e.g. human from mouse targets). Name kinds also carry 'name'
(rdfs:label); ASSAY rows instead carry 'description' (the free-text assay
description, name=null) and a relevance 'score' (higher = better match).
An EMPTY 'results' additionally carries 'hint'. Read it: an empty result is NOT an endpoint failure, and must not be reported as one. On a real endpoint failure this tool does NOT raise — it returns a dict with a single 'error' key instead; CHECK FOR 'error' BEFORE READING 'results'.
Inputs: name, term, limit, query, +5 more. Returns: object
search_chembl_moleculeARead-only
Resolve a DRUG / COMPOUND / MOLECULE (by name or structure) to a ChEMBL ID.
✅ Use this tool for drug, compound, or molecule names
(e.g., "sorafenib", "imatinib", "aspirin", "Gleevec").
⚠️ For biological targets (proteins, receptors, enzymes, genes such as
EGFR, BRCA1, TP53), use search_chembl_target instead.
Resolution path is auto-selected from the query shape:
• NAME / BRAND / SYNONYM → deterministic SPARQL, EXACT (case-insensitive) match on the molecule's skos:altLabel synonyms (which include brand and trade names — "Gleevec" → CHEMBL941 IMATINIB). Not fuzzy/substring: fix typos before calling. No relevance ranking to second-guess.
• InChIKey / InChI → deterministic SPARQL, EXACT (case-SENSITIVE) match on the RDF-stored identifier. These are canonical (toolkit-independent), so exact match is correct, e.g. "BSYNRYMUTXBXSQ-UHFFFAOYSA-N" → CHEMBL25.
• SMILES → the ChEMBL REST chemistry engine (flexmatch), NOT exact match: a SMILES is written differently by each toolkit, so flexmatch normalizes the structure first, e.g. "CC(=O)Oc1ccccc1C(=O)O" → CHEMBL25.
Structure detection is conservative (multi-word input, or input without the "InChI=" prefix / InChIKey pattern / structural punctuation, is treated as a name), so a bare-chain SMILES like "CCO" is treated as a name.
The search string can be passed as any of: query (canonical), search,
term, keyword, keywords, search_term, or name.
⚠️ mode='extract' — for a string that NAMES a drug rather than IS one.
Exact matching (the default) cannot resolve a clinical-trial intervention
string, a dosed/formulated product, or a multi-drug regimen, because none
of those is a synonym of anything: "Ustekinumab 90 mg", "Diclofenac SR",
"Ropivacaine 10% + Clonidine 1 µg/kg" all return 0 rows under 'exact'.
mode='extract' instead finds every substance NAMED INSIDE the string,
returning one result per distinct drug — so the combination above yields
ROPIVACAINE and CLONIDINE. Nested synonyms collapse to the longest match
("Sofpironium Bromide Gel" → SOFPIRONIUM BROMIDE, not also BROMIDE).
Use it as the RETRY when 'exact' returns nothing, not as the first call:
it is a text-extraction heuristic, so treat a hit as a candidate to
confirm, and note that it resolves a regimen to its COMPONENTS — it will
never return "FOLFIRI" itself, only the drugs a string spells out.
RETURNS a dict {'total_count', 'has_more', 'results'}. total_count is rows
RETURNED (capped by limit), not the full match count; has_more is true if
more exist beyond this page. Each result has 'chembl_id' (e.g. "CHEMBL25") and
'name' (rdfs:label, may be None for some structure hits). Under
mode='extract' each result additionally carries 'matched_span' (the text
that matched) and 'match_type' ('exact' if the span is the whole query,
else 'contained') — CHECK 'match_type' before trusting a hit. When a call
returns no results, a 'note' key explains why and what to try next. On
endpoint/HTTP failure this tool does NOT raise — it returns a dict with a
single 'error' key instead; CHECK FOR 'error' BEFORE READING 'results'.
Inputs: mode, name, term, limit, +5 more. Returns: object
search_chembl_targetARead-only
Resolve a biological TARGET (protein/receptor/enzyme) to a ChEMBL ID.
⚠️ DO NOT use this tool to look up drugs, compounds, or molecules by name.
For drug/compound/molecule names (e.g., "sorafenib", "imatinib", "aspirin"),
use search_chembl_molecule instead.
Resolution is deterministic SPARQL against the ChEMBL RDF graph, not a lexical
search — there is no ranking to second-guess:
• UNIPROT ACCESSION (e.g. "P00533") → the structured skos:exactMatch link.
Returns every target containing that protein (the single protein plus any
complex/family/chimera it participates in) — filter target_type to get
just one.
• GENE SYMBOL / PROTEIN NAME (e.g. "EGFR", "epidermal growth factor
receptor") → EXACT (case-insensitive) match, tried against BOTH the
target's own name and its protein component's skos:altLabel synonyms.
• If that finds nothing, ONE substring pass over target names runs as a
fallback (e.g. "dehydrogenase"). Still never fuzzy — fix typos.
Every result carries organism and type, so a symbol shared across species
or complexes is disambiguated by inspecting those fields (or by passing the
organism/target_type filters) — NOT by trusting order.
Target-type values (for type and the target_type filter): SINGLE PROTEIN,
PROTEIN COMPLEX, PROTEIN FAMILY, PROTEIN-PROTEIN INTERACTION, CHIMERIC PROTEIN,
NUCLEIC-ACID, CELL-LINE, TISSUE, ORGANISM, SELECTIVITY GROUP, SMALL MOLECULE,
OLIGOSACCHARIDE, LIPID, METAL, and other rarer kinds. An unrecognized
target_type raises rather than silently matching nothing.
The search string can be passed as any of: query (canonical), search,
term, keyword, keywords, search_term, or name.
RETURNS a dict {'total_count', 'has_more', 'results', 'match_mode'}.
total_count is rows RETURNED (capped by limit), not the full match count;
has_more is true if more exist beyond this page. Each result has
'chembl_id', 'name' (rdfs:label), 'organism', and 'type'. match_mode is
'exact', 'substring', or 'none' — 'substring' means the exact pass found
nothing and these are looser, UNRANKED matches, so verify 'name' before using
them; 'none' means both passes ran and neither matched.
An EMPTY 'results' additionally carries 'hint'. Read it: an empty result is NOT an endpoint failure, and must not be reported as one. On a real endpoint failure this tool does NOT raise — it returns a dict with a single 'error' key instead; CHECK FOR 'error' BEFORE READING 'results'.
Inputs: name, term, limit, query, +6 more. Returns: object
search_mesh_descriptorARead-only
Search for MeSH ID by query.
RETURNS a JSON-formatted string of the search results. On upstream/HTTP failure this tool does NOT raise — it returns a plain string beginning with "Error:" (not JSON). CHECK FOR the "Error:" prefix BEFORE parsing.
Inputs: name, term, limit, query, +4 more. Returns: result
search_pdb_entityARead-only
Search PDBj for structures, chemical components, or BIRD molecules.
Returns rich, named fields per hit (not just the title) — for pdb,
each result carries the experimental method, resolution, bound ligands,
and citation; for cc, the formula, SMILES, and InChI.
RETURNS a JSON string {"total": int | null, "results": [ {…fields…} ]}.
total is null when PDBj gives no count (typical for structured-filter
searches) — that is NOT zero and does NOT mean "no results"; consult
results directly. On upstream/HTTP failure returns a JSON object with an
error key instead — CHECK FOR error BEFORE reading results.
Inputs: db (required), name, term, limit, +13 more. Returns: result
search_reactome_entityARead-only
Search the Reactome pathway knowledgebase by keyword (name / fuzzy match).
Resolves a term (pathway / reaction / protein / complex / small-molecule name) to Reactome stable IDs. Matching is keyword/fuzzy — UNLIKE the exact-match ChEMBL search tools, so expect ranked, approximate hits.
RETURNS a dict {'total_count', 'has_more', 'results'} — NOT a bare list.
total_count is the number of records RETURNED (capped by limit);
has_more is true if more matched beyond the cap. Each result carries
'id' (stable Reactome stId, e.g. "R-HSA-109581"), 'name', 'type' (facet
type), 'exactType' (specific BioPAX-ish class), 'species' (list), and — only
when include_summation=True — 'summation' (≤240-char description). On
upstream failure returns {'error': ...} instead — CHECK FOR 'error' BEFORE
READING 'results'.
species and types are validated case-INSENSITIVELY against Reactome's
controlled vocabularies and normalized to canonical casing before dispatch:
the server-side filter is case-SENSITIVE and silently ignores a mis-cased
value (returning UNFILTERED results), so a mis-cased species used to lose
most hits. An unrecognized species/type now RAISES rather than silently
returning the wrong rows.
Inputs: name, rows, term, limit, +8 more. Returns: object
search_rhea_entityARead-only
Search the Rhea reaction database by keyword and return matching reactions.
Matching is KEYWORD/FUZZY over reaction participants, equations, EC numbers,
and cross-references — NOT exact-ID lookup. A term like "glucose" matches any
reaction mentioning glucose. Field-scoped terms and wildcards are supported
(e.g. ec:1.1.1.1, chebi:17234, uniprot:*). A chebi:-scoped term takes
a BARE ChEBI number, not the CHEBI: prefix; a redundant chebi:CHEBI:17234
is auto-corrected to chebi:17234 (the prefixed form otherwise 500s).
RETURNS a dict {'total_count', 'has_more', 'results'} — NOT a bare list.
'total_count' is the number of reactions RETURNED (capped by limit, max
500); 'has_more' is true if more matched beyond the cap. Each result carries
the requested columns as snake_cased keys (e.g. 'rhea-id' → 'rhea_id',
'chebi-id' → 'chebi_id'). On upstream failure returns {'error': ...} instead
— CHECK FOR 'error' BEFORE READING 'results'.
Valid columns (default rhea-id,equation): rhea-id, equation, chebi,
chebi-id, ec, uniprot, go, pubmed, reaction-xref(EcoCyc|KEGG|MetaCyc|
Reactome|M-CSA).
Inputs: name, term, limit, query, +5 more. Returns: object
search_uniprot_entityARead-only
Search for a UniProt entity ID by query.
⚠️ Only the search string and limit are accepted. Extra parameters
like taxon, organism, reviewed, species, etc. are silently
dropped and have no effect — express such filters inside the Solr
query string instead (e.g., organism_id:9606 AND reviewed:true).
⚠️ An unrecognised FIELD NAME inside the query string is not silently
ignored: UniProt rejects it (HTTP 400, "'taxon' is not a valid search
field") and this tool returns the "Error:" string described below.
Common wrong guesses that fail this way: taxon, organism, species,
go_id. What CAN fail silently is a valid field given an ill-formed
value — it returns 0 rows, or rows you did not expect, with HTTP 200.
The search string can be passed as any of: query (canonical),
search, term, keyword, keywords, search_term, or name.
RETURNS a TSV string with columns: accession, protein_name, organism_name. On upstream/HTTP failure this tool does NOT raise — it returns a plain string beginning with "Error:" (not TSV). CHECK FOR the "Error:" prefix BEFORE parsing rows.
Inputs: name, term, limit, query, +4 more. Returns: result
togoid_convertIdARead-only
Convert identifiers from one database to another.
Maps IDs between biological databases — e.g., NCBI Gene IDs to UniProt accessions, or UniProt accessions to PDB structure IDs.
RETURNS a JSON string of a bare array of [source_id, target_id] pairs, e.g. '[["672", "P38398"], ["675", "O15129"]]'. An empty array means none of the input IDs converted along the route.
Inputs: ids (required), route (required), limit, offset. Returns: result
togoid_countIdARead-only
Check how many of your IDs can be converted before doing bulk conversion.
A lightweight pre-check: tells you how many source IDs have mappings in the target database WITHOUT actually returning the mapped IDs. Use this to: - Verify your IDs are in the correct format - Estimate result size before a large convertId call - Check if a conversion route works for your specific IDs
This is a single-hop, pairwise check: pass source and target as two
separate args (unlike convertId, which takes one comma-joined route).
Inputs: ids (required), source (required), target (required). Returns: object
togoid_getAllDatasetARead-only
List all databases registered in TogoID with their ID formats.
Returns configuration for every dataset TogoID knows about, including:
label: Human-readable database name
regex: Pattern for validating IDs (helps you check if you have the right ID format before converting)
prefix: URI prefix for linked data
examples: Sample IDs you can use to test conversions
Useful for: - Discovering which databases are available for ID conversion - Checking the expected ID format (e.g., UniProt accession vs entry name) - Finding example IDs to test with countId before bulk conversion
Returns: Dictionary mapping dataset keys (e.g., 'uniprot', 'ncbigene', 'pdb') to their configuration objects.
Inputs: no named parameters. Returns: object
togoid_getAllRelationARead-only
Discover all available ID conversion routes between databases.
⚡ PLANNING TOOL — Call this EARLY when a question involves 2+ databases that are on DIFFERENT SPARQL endpoints and you need to map IDs between them.
Returns a map of all source→target database pairs that TogoID can convert. Use this to plan your cross-database strategy BEFORE attempting SPARQL joins or manual ID lookups.
Common conversion routes include: - ncbigene ↔ uniprot (Gene IDs to/from protein accessions) - uniprot ↔ pdb (Protein accessions to/from 3D structure IDs) - ncbigene ↔ ensembl_gene (NCBI Gene to/from Ensembl gene IDs) - chembl_target ↔ uniprot (Drug targets to/from protein accessions) - ncbigene ↔ hgnc (Gene IDs to/from HGNC symbols) - pubchem_compound ↔ chembl_compound (Compound IDs across databases)
When to use: - Question references 2+ databases on different SPARQL endpoints - You need to bridge identifiers (e.g., "find UniProt proteins for these NCBI Gene IDs") - Before writing complex multi-step SPARQL to join databases manually
When NOT to use: - Both databases share a SPARQL endpoint (use a single SPARQL query) - You only need data from one database - NCBI esearch can already cross-reference what you need
Returns: Dictionary mapping database pairs to their relationship metadata. Each entry shows source, target, and the nature of the link.
Inputs: no named parameters. Returns: object
togoid_getDatasetARead-only
Get configuration for a specific database in TogoID.
Retrieves detailed metadata about a single dataset, including its ID format, URI prefix, example IDs, and available annotations.
RETURNS a dict with label (human-readable name), regex (ID-validation
pattern — use it to check your IDs are well-formed), prefix (URI prefixes
for linking), examples (sample IDs — test with countId before bulk
conversion), and annotations (available annotation types).
Inputs: dataset (required). Returns: object
togoid_getDescriptionARead-only
Get human-readable descriptions for all databases in TogoID.
Returns names, descriptions (in English and Japanese), and organization info for each registered database. Useful for understanding what each database contains when planning cross-database queries.
Returns: Dictionary keyed by dataset name with description metadata.
Inputs: no named parameters. Returns: object
togoid_getRelationARead-only
Check if a specific ID conversion route exists and get its details.
Use this to verify that a particular source→target conversion is available before calling convertId. Also reveals the nature of the relationship (e.g., "encoded by", "has structure", "is target of").
This is a single-hop, pairwise check: pass source and target as two
separate args (unlike convertId, which takes one comma-joined route).
RETURNS a JSON string of a bare array of relationship objects, each with
forward (label from source to target), reverse (label from target to
source), and description (explanation of the link). An empty array means
no direct route exists.
Inputs: source (required), target (required). Returns: result
TogoMCP_Usage_GuideARead-only
⚠️ CALL THIS TOOL FIRST every turn, before any other TogoMCP tool.
Returns the v6 Usage Guide, which enforces the empirically-validated workflow:
GATE 0: classify the question (bounded → STEP −1 | open-ended → EXPLORATION).
STEP −1: analyze entities, databases, endpoints (no tools).
STEP 0: pick database(s) from the DATABASE CATALOG in this guide — no tool call.
STEP 1: specialized search or ncbi_esearch — ground in real IRIs.
STEP 2: get_MIE_file(database) — required before any run_sparql.
STEP 3: run_sparql() — pin every graph; LIMIT 10 first; max 2 consecutive.
STEP 4: synthesize — each fact once, no meta-commentary.Why this matters (measured): questions with ≥3 consecutive run_sparql calls score ~1.1 points lower than compliant ones; jumping to text search before reading the MIE schema accounts for ~95% of silent SPARQL failures. The guide's DATABASE CATALOG lists all databases with what each is for (scan it to pick 1–3), plus the EXPLORATION habits (Seed Definition, concierge check, prioritized Next Steps) for open-ended deep dives.
Most RDF Portal endpoints host MANY databases (primary: 16, ebi: 5, ncbi: 5, sib: 4) and every endpoint hosts many GRAPHS. An unpinned query silently reads all of them, so a co-hosted graph can supply a predicate you believe is native and return a plausible, correctly-shaped, WRONG number — with no error. The guide's CO-TENANCY section is the one to read before writing SPARQL.
Re-run GATE 0 every turn — prior workflow does not carry forward.
Returns: str: The content of the TogoMCP usage guide.
Inputs: no named parameters. Returns: result
togovar_search_diseaseARead-only
Resolve a disease term to MONDO / MedGen IDs for variant search.
The returned mondo_id (or MedGen CUI) is what search_variant takes as
disease_id. Both land directly on TogoMCP's existing mondo/medgen RDF
databases and TogoID nodes.
The TogoVar endpoint does loose token matching with no relevance order (a
query like "cystic fibrosis" also returns unrelated "Hepatic fibrosis…"
rows), so this tool RE-RANKS client-side: exact label match first, then
prefix, then whole-word, then loose token matches last. Each result carries
match_type ("exact"|"prefix"|"word"|"fuzzy") — a top hit that is not
exact means no exact label matched.
COVERAGE LIMIT: TogoVar only indexes diseases that have ClinVar/MGeND
variant associations, so some canonical/parent MONDO terms are simply absent
here (e.g. MONDO_0007254 "breast cancer" does NOT appear in these results).
But a broad/parent MONDO ID still WORKS as a disease_id in search_variant
even when unlisted here — the variant search resolves it via MONDO descendant
expansion (MONDO_0007254 -> ~24,550 variants). So if you know or can resolve
the canonical MONDO ID (e.g. via OLS4 or the mondo RDF database), pass it
straight to search_variant; do not assume this resolver is exhaustive.
Inputs: limit, query. Returns: result
togovar_search_geneARead-only
Resolve a human gene symbol/alias to its HGNC ID for variant search.
This is the FIRST step of the two-step variant workflow: the hgnc_id
returned here is what search_variant takes as gene_hgnc_id.
The TogoVar endpoint does loose token matching with no relevance order (it
returns the same set for "ALDH2" and the non-existent "ALDH2A1"), so this
tool RE-RANKS client-side: exact symbol match first, then prefix, then other
matches. Each result carries match_type ("exact"|"prefix"|"word"|"fuzzy")
against your query — CHECK IT: if the top hit is not exact, the exact
symbol you asked for does not exist and the rows are loose false positives,
so do not blindly feed the first hgnc_id downstream. (The endpoint echoes
the matched token as symbol and the HGNC approved gene name as name; it
does not expose approved-vs-alias status, so use name to sanity-check.)
Inputs: limit, query. Returns: result
togovar_search_variantARead-only
Search TogoVar for human genome variants with population frequencies.
TogoVar integrates allele frequencies from gnomAD, ToMMo (Japanese), NCBN, GEM-J, JGA, and BioBank Japan, plus ClinVar + MGeND clinical significance and SIFT/PolyPhen/AlphaMissense predictions — data with no SPARQL counterpart elsewhere in TogoMCP.
All filters are optional and combined with AND. Supply zero filters to browse; but scope tightly — the database holds ~1 billion variants.
COUNTS: total is the size of the whole REST backend (1,097,708,150) and is
constant across queries; filtered is the count matching your filters. Note
the REST backend is LARGER than TogoMCP's togovar SPARQL graph (~2.8x: the
SPARQL side is the annotated subset, 390,725,782), so REST counts will not
match SPARQL COUNT(*) — they measure different sets.
PAGING CAP: the API allows offset + limit <= 10,000 and returns HTTP 400
beyond it, so a result set larger than 10,000 cannot be fully paged. Narrow the
filters until filtered <= 10,000 to enumerate one exhaustively.
STATISTICS SCOPE (stat=True): all facets are scoped to the filtered set, but
they count at different granularities. type counts per variant (sums to
filtered); dataset per variant-cohort; consequence per
variant-TRANSCRIPT (VEP fan-out, so its sum is filtered x transcripts per
variant — ~5-6 for a typical gene, 400+ in transcript-dense loci like
BRCA1); significance per variant-condition record. So consequence/
significance sums exceed filtered and must NOT be summed against it (they
are not per-variant counts). See statistics_caveats for the per-facet rule.
ROUND-TRIP TO SPARQL: gate on tgv_id. It is NULL for variants that exist in
the REST backend but NOT in the (smaller) SPARQL subset — including some
ClinVar-Pathogenic ones. variant_iri is emitted ONLY when tgv_id is
non-null, so a non-null variant_iri is safe to query in the togovar SPARQL
graph; a row with tgv_id: null has no SPARQL record at all, and REST is the
only source for it.
TWO-STEP WORKFLOW for gene/disease filters:
1. search_gene("ALDH2") -> hgnc_id -> pass as gene_hgnc_id.
2. search_disease("breast cancer") -> mondo_id -> pass as disease_id.
Inputs: stat, stop, limit, start, +16 more. Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 29 tools
Most tools are cleanly separated by database/resource prefix (uniprot, pubchem, pdb, chembl, ncbi, togoid, togovar) and by action. The main ambiguity is the three ChEMBL search tools and the two TogoID relation tools, but their descriptions explicitly distinguish exact-name lookup, target lookup, and cross-entity lookup.
The set mixes snake_case (search_uniprot_entity, get_MIE_file, ncbi_esearch) with camelCase (togoid_getAllRelation, togoid_convertId) and inconsistent verb styles (ncbi_esearch vs. ncbi_list_databases vs. togoid_getRelation). Each subsystem is internally consistent, but there is no single predictable pattern across the whole server.
At 29 tools, the server is above the comfortable range, but the broad multi-database scope (RDF, ChEMBL, NCBI, TogoID, TogoVar) justifies much of the surface. Some TogoID metadata tools and the mandatory usage-guide tool inflate the count and could likely be consolidated.
The set covers a full read-only workflow: discover endpoints, read MIE schemas, run SPARQL, resolve entities through database-specific searches, convert IDs, and fetch NCBI/TogoVar records. Minor gaps exist — e.g., no direct search wrapper for RDF databases like Ensembl or GO — but run_sparql and TogoID provide workarounds.
Maintenance
Related MCP Connectors
MCP server for querying BrainKB, a knowledge base for neuroscience knowledge graphs.
Auditable MCP server for PubMed, Europe PMC, ClinicalTrials.gov, and bioRxiv/medRxiv queries
MCP gateway federating 22 biomedical MCP servers behind one endpoint: gnomAD, ClinVar, HPO, VEP.
One MCP server for the services your AI needs: memory, files, Microsoft 365, kanban and more.
Related MCP Servers
- AlicenseBqualityBmaintenanceAn MCP server that provides standardized access to biomedical knowledge bases and resources, enabling AI systems to retrieve verified information from sources like bioRxiv, EuropePMC, and various protein/gene databases.5231Apache 2.0
- AlicenseAqualityDmaintenanceAn MCP server that provides direct access to PubMed and PubMed Central via the NCBI E-utilities API. It enables AI models to search biomedical literature, retrieve detailed article metadata, and download open-access full texts.5MIT
- AlicenseNot gradedqualityDmaintenanceA unified MCP server for biomedical research that connects AI systems to resources like Ensembl, EuropePMC, STRING, and more, enabling retrieval of verified domain-specific information.Apache 2.0
- AlicenseAqualityBmaintenanceA 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.43173 npm12Apache 2.0