biodatafinder
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., "@biodatafindersearch for lung adenocarcinoma single-cell RNA-seq datasets in humans"
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.
biodatafinder
An MCP server and CLI that searches several public life-science data repositories with one query and returns a single ranked list of datasets.
Finding reusable data usually means repeating the same search in GEO, ENA, CELLxGENE, PRIDE and a few generalist repositories, each with its own query syntax, organism filter and metadata fields. biodatafinder sends one query to all of them concurrently, expands disease, tissue and cell-type terms through EBI's Ontology Lookup Service (OLS4), maps every result onto one record shape (accession, title, organism, assay, sample count, access, license, DOI, link), ranks the merged list, and reports any source that failed instead of hiding it.
Source | What it covers | API |
| NCBI GEO series (GSE): expression and other functional genomics | E-utilities ( |
| European Nucleotide Archive studies (PRJ*/ERP/SRP) | ENA Portal API |
| CZ CELLxGENE Discover single-cell collections | Curation API v1 |
| PRIDE Archive mass-spectrometry proteomics (PXD) | PRIDE Archive API v3 |
| Dataset DOIs from Zenodo, Figshare, Dryad, Mendeley Data, MassIVE and others | DataCite REST API |
No API keys are needed. Metadata is taken as each API returns it: when a repository does not report a sample count, license or access level, the field is left empty rather than guessed.
Install
Requires Python 3.11+ and uv.
Run without installing:
uvx --from git+https://github.com/fmdelgado/biodatafinder biodatafinder search "lung adenocarcinoma"Or from a checkout:
git clone https://github.com/fmdelgado/biodatafinder
cd biodatafinder
uv sync
uv run biodatafinder search "lung adenocarcinoma"Optional environment variables:
NCBI_API_KEY: raises the NCBI E-utilities limit from 3 to 10 requests/s (GEO).NCBI_EMAIL: sent to NCBI with each request, as NCBI asks.
Related MCP server: BioTrax
Use with Claude
Claude Code
claude mcp add biodatafinder -- uvx --from git+https://github.com/fmdelgado/biodatafinder biodatafinder-mcpClaude Desktop
Add to claude_desktop_config.json (Settings > Developer > Edit Config):
{
"mcpServers": {
"biodatafinder": {
"command": "uvx",
"args": [
"--from",
"git+https://github.com/fmdelgado/biodatafinder",
"biodatafinder-mcp"
],
"env": { "NCBI_API_KEY": "optional" }
}
}
}Skill
skills/find-datasets/SKILL.md is a Claude skill that tells
Claude how to use these tools with a scientist: clarify requirements, search broad then
narrow, check top hits with get_dataset, and report only datasets the tools returned.
Copy the skills/find-datasets folder into ~/.claude/skills/ (Claude Code) or upload it
as a skill in Claude.
CLI
biodatafinder search TEXT [--organism NAME] [--data-type TYPE ...] [--source NAME ...]
[--min-samples N] [--open-only] [--limit N] [--no-ontology] [--json]
biodatafinder get SOURCE ACCESSION--limit is per source. --json prints the full response, including the ontology terms the
query was expanded with and any per-source errors. n=? means the source did not report a
sample count.
Output observed on 2026-09-24 (results change as repositories grow):
$ biodatafinder search "lung adenocarcinoma single-cell RNA-seq" --organism "Homo sapiens" --limit 3
3.60 [ena] PRJDB5904 n=? Combinatory use of the distinct single cell RNA-seq analytical platforms reveals heterogen
https://www.ebi.ac.uk/ena/browser/view/PRJDB5904
3.60 [ena] PRJNA647741 n=? Long and short-read single cell RNA-seq profiling of human lung adenocarcinoma cell lines
https://www.ebi.ac.uk/ena/browser/view/PRJNA647741
3.43 [ena] PRJNA1471638 n=? Single-Cell RNA Sequencing Identifies Stem-Like Subpopulations and Their Gene Signature in
https://www.ebi.ac.uk/ena/browser/view/PRJNA1471638
2.93 [datacite] 10.7910/dvn/iieaj5 n=? Neuroendocrine-related prognostic risk model and tumor immune environment modulation in lu
https://doi.org/10.7910/dvn/iieaj5
2.85 [cellxgene] 0bebef1a-4607-4584-9070-dacf89a0d635 n=? Defining the cellular and molecular identities of histologic subtypes in lung adenocarcino
https://cellxgene.cziscience.com/collections/0bebef1a-4607-4584-9070-dacf89a0d635
2.60 [geo] GSE335637 n=6 Tumor-derived exosomal METTL3 reprograms macrophages through the m6A–IGF2BP2–ATG2A axis to
https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE335637
2.43 [cellxgene] 6f6d381a-7701-4781-935c-db10d30de293 n=? The integrated Human Lung Cell Atlas
https://cellxgene.cziscience.com/collections/6f6d381a-7701-4781-935c-db10d30de293
...$ biodatafinder search "Alzheimer's disease" --data-type proteomics --limit 5
3.10 [pride] PXD079144 n=? Serine-65 phosphorylated ubiquitin associates with soluble Tau and seeding activity in Alz
https://www.ebi.ac.uk/pride/archive/projects/PXD079144
3.10 [pride] PXD075747 n=? Small Molecule Guided Small Molecule Guided Photocatalytic Proteomics Profiling of Amyloid
https://www.ebi.ac.uk/pride/archive/projects/PXD075747
3.10 [pride] PXD075438 n=? Glycoproteomics of Human and Mouse Brains in Alzheimer’s Disease
https://www.ebi.ac.uk/pride/archive/projects/PXD075438
3.00 [datacite] 10.25934/pr00012874.0 n=? Available datapackage for study 'Donanemab Follow-On Study: Safety, Tolerability, And Effi
https://doi.org/10.25934/pr00012874.0
...
2.00 [datacite] 10.25345/c5bn9xh7v n=? MassIVE MSV000103338 - Alzheimer's Disease Neuroimaging Initiative (ADNI) cerebrospinal fl
https://doi.org/10.25345/c5bn9xh7v
...$ biodatafinder search "gut microbiome metabolomics" --organism "Mus musculus" --limit 3
3.38 [ena] PRJNA1347090 n=? Short-Term Exposure to Environmentally Relevant doses of Chlorpyrifos Impact both the Gut
https://www.ebi.ac.uk/ena/browser/view/PRJNA1347090
...
2.88 [datacite] 10.5281/zenodo.22865761 n=? Multi-omics dataset of gut microbiome, serum metabolome, and whole-blood transcriptome in
https://doi.org/10.5281/zenodo.22865761
2.50 [geo] GSE316703 n=50 Microbiota-Derived Isovalerate Ameliorates Sex-Specific Gut Barrier Dysfunction in Malnutr
https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE316703
...$ biodatafinder get geo GSE2034
{
"source": "geo",
"accession": "GSE2034",
"title": "Breast cancer relapse free survival",
"url": "https://www.ncbi.nlm.nih.gov/geo/query/acc.cgi?acc=GSE2034",
"description": "This series represents 180 lymph-node negative relapse free patients and 106 lymph-node negate patients that developed a distant metastasis. ...",
"organisms": ["Homo sapiens"],
"data_type": "transcriptomics",
"assay": "Expression profiling by array",
"tissues": [],
"diseases": [],
"sample_count": 286,
"access": "open",
"license": null,
"publication_date": "2005-02-23",
"doi": null,
"pubmed_ids": ["15721472"]
}Tips: put the organism in --organism rather than in the text (each source applies it in
its own way), and keep the text to the topic. The ontology expansion only fires when the
whole text matches an ontology label or synonym, so "NSCLC" expands to
non-small cell lung carcinoma (MONDO:0005233) while "NSCLC scRNA-seq" is searched as
written.
MCP tools
search_datasets
Searches all registered sources at once and returns a ranked SearchResponse.
Parameter | Type | Default | Meaning |
| string | required | What the data should contain, e.g. |
| string | none | Scientific or common name, e.g. |
| list | all | Any of |
| list | all | Restrict to source names from |
| int | none | Drop records with a known sample count below this; records with unknown count are kept |
| bool | false | Drop records marked |
| int | 10 | 1 to 100 |
| bool | true | Expand the text and organism through OLS4 |
The response has results (records sorted by score), errors (one entry per source that
failed or timed out after 20 s), sources_queried, and query (including expanded_terms).
Each record has: source, accession, title, url, description, organisms,
data_type, assay, tissues, diseases, sample_count, access (open, controlled,
unknown), license, publication_date, doi, pubmed_ids, score.
get_dataset
get_dataset(source, accession) returns the full record for one accession, or null if the
source does not have it. Accepted accessions: GEO GSE...; ENA PRJ..., ERP..., SRP...;
CELLxGENE collection UUID; PRIDE PXD...; DataCite DOI (bare, doi: or https://doi.org/).
list_sources
Lists the sources with their description, data types and homepage.
What each source reports
Field | geo | ena | cellxgene | pride | datacite |
sample count | yes (samples) | no | no (cell count in description) | no | no |
organism | yes | yes | yes | yes | no |
assay | GEO series type | no | yes | experiment type + instrument | no |
tissues / diseases | no | no | yes | yes | no |
access | open | open | open | open | from rights statements, else unknown |
license | no | no | no | detail only ( | from rights list |
DOI | no | no | paper DOI | PRIDE dataset DOI | the dataset DOI |
Source-specific behaviour:
geo: esearch then esummary; the API has no relevance sort, so the per-source list is the newest matching series and ordering comes from biodatafinder's ranker. Requests are spaced to stay under NCBI's rate limit, with one retry on HTTP 429.
ena: every word (3+ characters) of a search term must appear in the study title or description; terms are ORed. Common organism names (human, mouse, rat, zebrafish) are mapped to scientific names; a numeric organism is treated as an NCBI taxon ID (includes subtaxa).
cellxgene: the API has no search endpoint, so the full collection listing (~3 MB) is downloaded once per process (cached 6 h) and matched locally. The first search takes ~7 s.
pride: keyword search has no OR, so expanded terms are extra requests used only to top up the results. Words such as "proteomics" are dropped from the keyword because every PRIDE project is proteomics and the search requires every word. The organism filter is applied locally on the returned labels.
datacite: DataCite has no organism field, so
organismdoes not affect DataCite results. Zenodo/Figshare version DOIs with the same title and publisher are collapsed to one record.
Architecture
src/biodatafinder/
models.py SearchQuery, DatasetRecord, SearchResponse (pydantic)
ontology.py OlsExpander: query text and organism -> OLS4 terms + synonyms (best effort)
sources/ one adapter per repository, all subclasses of sources/base.py:Source
registry.py source name -> adapter class
federation.py expand, fan out to sources concurrently (20 s timeout each), collect errors
ranking.py filter (min_samples, open_access_only), dedupe by DOI, score, sort
server.py MCP server (mcp 2.x MCPServer): search_datasets, get_dataset, list_sources
cli.py `biodatafinder search` / `biodatafinder get`Ranking is a transparent heuristic, not a learned model. For each phrasing of the query (the original text, then ontology labels and synonyms at weight 0.8) it takes the share of query words found in the title (weight 2) and in the other metadata (weight 1); assay words such as "single", "cell", "RNA", "seq" count a quarter of a topic word. Small bonuses are added for a matching organism (+0.5), sample count (up to +0.3) and open access (+0.1). The best phrasing wins.
Adding a source
Create
src/biodatafinder/sources/<name>.pywith aSourcesubclass:"""<Repository> via <API name>. Docs: <link to API docs>""" from biodatafinder.models import Access, DatasetRecord, DataType, SearchQuery from biodatafinder.sources.base import Source API = "https://example.org/api" class ExampleSource(Source): name = "example" description = "One line on what the repository holds." data_types = (DataType.METABOLOMICS,) homepage = "https://example.org" async def search(self, query: SearchQuery) -> list[DatasetRecord]: r = await self.client.get( f"{API}/search", params={"q": query.search_terms()[0], "size": query.limit_per_source}, ) r.raise_for_status() return [self._to_record(hit) for hit in r.json()["hits"]] async def get(self, accession: str) -> DatasetRecord | None: r = await self.client.get(f"{API}/studies/{accession}") if r.status_code == 404: return None r.raise_for_status() return self._to_record(r.json()) def _to_record(self, hit: dict) -> DatasetRecord: return DatasetRecord( source=self.name, accession=hit["id"], title=hit["title"], url=f"https://example.org/studies/{hit['id']}", )Rules: use only
self.clientfor HTTP; return at mostquery.limit_per_sourcerecords; applyquery.organismin the API query when the API supports it;get()returnsNonefor not-found and raises on other HTTP errors; leave fields empty when the API does not provide them (never guess sample counts, access or license).Add one line to
SOURCE_CLASSESinregistry.py:"example": "biodatafinder.sources.example:ExampleSource",Add tests in
tests/sources/test_<name>.py:save a few real, trimmed API responses under
tests/fixtures/<name>/(keep each under 50 KB);offline tests with respx covering field mapping (check concrete values), the organism and limit parameters,
get()found,get()not found returningNone, and a 5xx raising;one
@pytest.mark.livetest with a realistic query against the real API.
Also add the name to the parametrized contract test in
tests/test_core.py.
Development
uv sync
uv run pytest # offline tests (live tests are deselected)
uv run pytest -m live -o addopts="" # live tests against the real APIs
uv run ruff check src tests && uv run ruff format --check src testsRoadmap
v0.2, more sources:
ArrayExpress / BioStudies
SRA
Human Cell Atlas Data Portal
Single Cell Portal (Broad)
MetaboLights
Metabolomics Workbench
NCI Genomic Data Commons (GDC)
GTEx
gnomAD
1000 Genomes
dbGaP (study metadata only)
Image Data Resource (IDR)
EMPIAR
PDB
Later: an optional locally harvested index for GEO and ENA, so that results can be ranked by relevance rather than by the order the APIs return them.
Known limitations in v0.1:
Ontology expansion only matches the whole query text; multi-concept queries are not split.
GEO, ENA and PRIDE return matches in their own order, not by relevance, so with a small
limit_per_sourcethe most relevant older datasets may not be fetched.Sample counts are only available from GEO.
License
MIT, see LICENSE.
Available Tools
3 toolsget_datasetA
Fetch full metadata for one dataset, e.g. source='geo', accession='GSE123456'.
| Name | Required | Description | Default |
|---|---|---|---|
| source | Yes | Source name, e.g. 'geo'. | |
| accession | Yes | Accession or DOI, e.g. 'GSE123456'. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description carries the full burden. 'Fetch' clearly implies a read-only operation and 'full metadata' signals what is returned, but there is no disclosure of behavior on missing/invalid accessions or any edge-case semantics. This is acceptable for a simple fetch tool but not richly transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single efficient sentence that front-loads the action and object, then gives a compact illustrative example. Every part earns its place and there is no filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a low-complexity tool with only two required parameters and an output schema, the description provides enough information to invoke the tool correctly. It does not describe not-found behavior, but that is not essential given the output schema and the straightforward fetch semantics.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so the baseline is 3. The description repeats the schema's own examples ('geo' and 'GSE123456') without adding new parameter constraints, format details, or relationship guidance beyond what the schema already provides.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('Fetch'), a clear resource ('full metadata for one dataset'), and the identifying parameters (source and accession). This distinguishes it from the sibling tools search_datasets and list_sources, since it targets exactly one known dataset rather than searching or enumerating.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The example implies the tool should be used when the caller already knows the source and accession and wants full metadata for a single dataset. However, it does not explicitly mention when not to use it or contrast it with search_datasets or list_sources.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_sourcesA
List the data sources this server can search, with the data types each covers.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the burden. It discloses the result shape (list of sources with data types) and implies a read-only listing operation, but it does not add details about authentication, pagination, or any constraints. This is adequate but minimal for a zero-parameter listing tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
A single sentence with no wasted words: it states the action, the scope, and the included detail. The key purpose is front-loaded and every word earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter enumeration tool with an output schema, the description is complete: an agent knows exactly what the tool returns and how it fits into the server's search workflow. No additional context is needed to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the description cannot add parameter-level information. The baseline of 4 applies because parameter semantics are not applicable and nothing about parameters is missing.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description names a specific verb ('List'), a specific resource ('data sources this server can search'), and the key content ('data types each covers'). This clearly differentiates it from sibling tools like search_datasets and get_dataset, which operate on individual datasets rather than enumerating available sources.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly implies the tool is for discovering which data sources are searchable before using search_datasets or get_dataset. It provides clear context on what the tool returns, though it does not explicitly state when not to use it or name alternatives directly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
search_datasetsB
Search all registered open data sources at once and return ranked datasets.
| Name | Required | Description | Default |
|---|---|---|---|
| text | Yes | What the data should contain, e.g. "lung adenocarcinoma scRNA-seq". | |
| sources | No | Restrict to these sources (see list_sources). Default: all. | |
| organism | No | Scientific or common name, e.g. 'Homo sapiens' or 'mouse'. | |
| data_types | No | Only query sources covering any of these data types. | |
| min_samples | No | Drop records with fewer samples. Records whose sample count is unknown (many sources do not report it) are kept. | |
| expand_ontology | No | Also search ontology synonyms of the text (EBI OLS). | |
| limit_per_source | No | Maximum records fetched from each source. | |
| open_access_only | No | Drop records marked controlled-access. Unknown access is kept. |
Output Schema
| Name | Required | Description |
|---|---|---|
| query | Yes | |
| errors | No | |
| results | Yes | |
| sources_queried | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations provided, the description must disclose behavioral traits. It mentions the ranked output, which adds value, but it does not state that the operation is read-only, any potential side effects, access restrictions, or rate limits. For a search tool this is a notable gap; the 'search' verb only implicitly suggests safety.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single concise sentence that front-loads the primary purpose and output. There is no filler or redundancy; every word contributes to understanding the tool's core function.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is minimal for a tool with 8 parameters and an output schema. It does not explain the ranking mechanism, the significance of the open-access qualifier, or how parameters like expand_ontology or min_samples affect results. While the output schema covers return values, the description fails to tie the high-level behavior to the many available options, leaving an agent without sufficient context for nuanced use cases.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% with detailed descriptions for all 8 parameters, so the baseline is 3. The tool description adds no parameter-specific information beyond what the schema already provides, leaving the parameters fully explained by the schema alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action (search), the resource (all registered open data sources), and the output (ranked datasets). It distinguishes itself from siblings like get_dataset (which retrieves a specific dataset) and list_sources (which lists sources) by emphasizing the cross-source, aggregated search scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage when a broad cross-source search is needed, but it does not explicitly mention when to use alternatives (get_dataset for a known dataset, list_sources to discover sources). No exclusions or conditional guidance is provided, so the agent must infer the appropriate context.
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.
3 tool updates
v0.1.0- First observed
get_dataset - First observed
list_sources - First observed
search_datasets
TDQS
Scored across 3 tools
Each tool has a clearly distinct purpose: search_datasets finds datasets, get_dataset retrieves metadata for a specific one, and list_sources enumerates available sources. No overlap or ambiguity between them.
All tool names follow the same verb_noun snake_case convention (search_datasets, get_dataset, list_sources). The naming pattern is consistent and predictable.
With 3 tools, the server is lean but well-scoped for its purpose of searching and retrieving biodata metadata. Each tool earns its place and the count falls within the ideal 3-15 range.
The tool set covers the core lifecycle of dataset discovery: listing sources, searching across them, and fetching full metadata. There are no obvious gaps or dead ends for the stated domain.
Maintenance
Related MCP Connectors
Semantic search across 5 US government healthcare databases.
Scholarly search: OpenAlex, Crossref, arXiv, OpenCitations and PubMed in one endpoint.
MCP gateway federating 22 biomedical MCP servers behind one endpoint: gnomAD, ClinVar, HPO, VEP.
- AmassOAuthtech.amass
Linked life-science search: 40M+ papers, 1.2M+ trials, drugs, genes, FDA/EMA approvals, patents.
Related MCP Servers
- AlicenseAqualityBmaintenanceSearches and fetches research datasets across Zenodo, DataCite (Dryad/Figshare/Dataverse/OSF), NCBI omics archives (GEO/SRA/BioProject), and the literature (PubMed/OpenAIRE) through one normalized model — deduplicating by DOI, expanding organism queries with NCBI Taxonomy synonyms, and bridging papers to the datasets they produced. Resolves citations and open-access full text, and downloads files.673 PyPI4MIT
- AlicenseNot gradedqualityDmaintenanceUnified genomic track, peak, and sequence retrieval tool for ENCODE, ChIP-Atlas, ReMap, GEO, and SRA/ENA with unified metadata, resolved DOI/PMID provenance, and direct FASTQ download without SRA toolkit.MIT
- AlicenseAqualityCmaintenanceAn 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.115,541 PyPI1Apache 2.0
- AlicenseAqualityDmaintenanceEnables searching the NIAID Data Ecosystem for biomedical research resources including datasets, clinical studies, and publications using Elasticsearch queries.3MIT