
BioMapper
io.github.trentleslie由 GitHub 账号 trentleslie 发布v1.6.3更新于 Nov 7, 2026
Resolve metabolite, lipid, protein, gene and lab names to knowledge-graph IDs.
概览
把代谢物、脂质、蛋白质、基因和检验项目名称映射为 CHEBI、HMDB、PubChem、RefMet 等知识图谱标准标识符。
- 可以做什么
- 查询支持的实体类型、词表和注释器
- 将单个名称(可附带标识符提示)映射为知识图谱 ID 与置信度等级
- 每次请求批量映射最多五个实体
- 把任意长度的 TSV 或 CSV 作为可续跑的后台任务处理,并查看、续跑或取消任务
- 查看服务器版本、知识图谱来源、限制以及允许访问的文件夹
- 适用场景
- 适合需要把表格、队列面板或实验室导出中的生物名称规范化为标准标识符,或在后续分析前确认某个名称能否高置信度解析的场景。也适用于依赖标识符级关联的跨队列协调工作。
- 运行要求
- 以本地 Python 包形式运行,用 uvx 启动(该命令需 1.6.2 或更高版本)。需要访问托管的 BioMapper API,默认无需密钥。可选环境变量:BIOMAPPER_API_KEY 用于自建或需认证的部署,BIOMAPPER_BASE_URL 指向其他 API 根地址,BIOMAPPER_MCP_HOME 指定任务状态目录,BIOMAPPER_MCP_ROOTS 指定 map_file 可读写的文件夹。
安装
在 SourceWeft 中
- 打开 控制台中的 BioMapper,将其添加到工作区。
- 为需要使用其工具的对话启用该服务。
Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。
其他 MCP 客户端
参照 仓库 中的启动说明。
README
biomapper
Python client for the BioMapper2 API — map biological entity names to standardized knowledge-graph identifiers (CHEBI, HMDB, PubChem, RefMet, and more).
Installation
The core install includes the MCP server for agents (Claude Code, Claude Desktop, other MCP
clients); launch it with uvx biomapper (see Use from an agent (MCP)).
Use 1.6.2 or later for uvx biomapper. 1.6.0 and 1.6.1 shipped the server behind an mcp
extra (uvx --from 'biomapper[mcp]' biomapper-mcp); that line still works on 1.6.2.
Use 1.5.6 or later for harmonize_cohorts() and ambiguous-link flags (see Harmonization).
Use 1.5.4 or later to call the hosted deployment without a key (see API keys).
Use 1.5.3 or later for the benchmark suite. Earlier published releases, up to and including
1.4.0, ship neither biomapper.benchmarks nor the benchmarks extra, so
pip install 'biomapper[benchmarks]' against them warns that the extra is unknown and installs
only the core client. 1.5.2 contains the suite but its extras were published empty, so the
same command installs the core client without pandas, requests, rdkit, openpyxl or defusedxml and
the suite fails on first import; install those by hand if you are pinned to 1.5.2. 1.5.3 is the
first release whose benchmarks extra actually carries its dependencies. The changelog records
which versions reached the index; 1.5.0 and 1.5.1 are tagged (not published).
Notebooks
notebooks/biomapper_tutorial.ipynb: the harmonization protocol end to end, keyless and build-pinned: resolve two cohort panels, link them by identifier-only CURIE sets, and read a certified and a refused structural certificate.notebooks/monti_overlap_benchmark.ipynb: BioMapper vs Monti et al. 2026 on the NECS cross-cohort overlap, as linked-count coverage for four cohorts plus a structural certification of the NECS to Arivale links, replayed from a pinned run with a small live check.notebooks/ukbb_arivale_harmonization_sop.ipynb: a standard operating procedure for harmonizing two cohorts with this package, worked on UK Biobank × Arivale (metabolites, proteins, clinical labs): inclusion rules, map, match, verify, and results asserted against the Activity 2 milestone, replayed offline from shipped panel metadata.
API keys (optional)
No API key is needed for the hosted deployment (https://biomapper.expertintheloop.io). From
1.5.4 the client is keyless by default: with no key configured it sends no X-API-Key header,
and every entry point, including the synchronous wrappers, works as shown below.
A key is only for a self-hosted or authenticated deployment. Pass it as api_key=, or set it in
your environment:
or in a .env file in your project root:
A configured key is sent unless anonymous=True is passed. To force a keyless call while BIOMAPPER_API_KEY is set, use
BioMapperClient(anonymous=True). If a deployment does require a key and none was sent, the first
request raises BioMapperAuthError saying so.
Releases before 1.5.4 raise BioMapperConfigError when no key is configured, and their
synchronous wrappers cannot reach a keyless deployment; upgrade, or use
BioMapperClient(anonymous=True) directly.
Quick start
Single lookup (synchronous)
Batch mapping (synchronous)
Inputs are auto-chunked at 1000 entities per request against the native
POST /map/batch endpoint, so 10,000 records cost 10 round-trips.
Dataset upload (synchronous)
For larger inputs, hand the server a TSV/CSV file directly and stream
results back. The server processes the file row-by-row over the
POST /map/dataset/stream endpoint:
name_column and provided_id_columns are required — the server uses
them to map your file's columns to entity names and identifier hints.
For per-result streaming into a UI or custom processing, use the async
BioMapperClient.map_dataset_file_iter method (see the tutorial
notebook in notebooks/).
Discovering what the API supports
Tuning resolution
The mapping calls accept the API's resolution options as keyword arguments. An option you do not pass is omitted from the request, so the server's own default applies and the payload is unchanged for callers who ignore them.
Coverage is uneven, so check this before reaching for one. Passing an option to a call that does
not accept it raises TypeError locally, before any request:
array_delimiters is absent from the dataset routes because the API does not accept it there. The
four missing from map_dataset_file_sync are a gap in that wrapper rather than an API limitation:
the async map_dataset_file_iter underneath it does accept them, so use that directly if you need
them on a file-based run.
kestrel_top_n populates result.kestrel_results with the raw rows Kestrel returned, exactly as
returned, for each search endpoint the pipeline used. Those rows are untrusted external data:
treat every field as unescaped and unverified.
Resolution certificates and refusal
A mapping result carries the structural certificate the API computed for chosen_kg_id, which is
how you tell "we could not check this" apart from "we checked and disagree".
state="contradicted" means a human should look, not that the resolver is wrong: a name lookup at
an external registry can itself return a related-but-different compound. state="unavailable"
means there was nothing to check against, which is unverifiable rather than wrong.
Async usage
map_dataset_file_iter is the primitive for UIs and custom processing that
want per-result reactivity. Callers needing a blocking, fully-collected
result should use map_dataset_file_sync instead (see above).
Jupyter notebooks
Apply nest_asyncio before using sync helpers inside a running event loop:
The worked notebooks are listed under Notebooks. Both run against the keyless hosted deployment, so no API key is needed, and both print the exact KRAKEN build that answered.
Preprocessing functions
Harmonization (cross-dataset equivalence)
biomapper.harmonize links two already-resolved datasets locally. It runs entirely on the
client: no extra requests, no knowledge-graph access, so it works offline and is fully testable
without a network. Two entities, one per cohort, link when any of these holds, and each link
records which one as its basis (strongest first):
Name links (from 1.5.5, opt-in with link_by_name=True) catch entities that resolution put
on different nodes, such as acetylcarnitine (c2) and acetylcarnitine (C2). They are currently
intended for small-molecule / metabolite panels; other entity types are pending review of
case-sensitive naming conventions (gene and protein symbols, for example). Rules:
- Only entities that resolved on both sides link by name; an unresolved one stays a refusal
candidate. Names are compared on
query_name, even when you pass a customkey=; links are reported under the keys. - No fuzzy matching and no punctuation stripping, only whitespace normalization.
- A casefold-only match where either name is
NAME_CASEFOLD_MIN_LENGTH_EXCLUSIVE(4) characters or fewer is withheld, not linked, and listed inreport.name_match_withheldfor review:Co(cobalt) andCO(carbon monoxide) are different things. - Pass results of one entity type per
harmonize()call. The results carry no type to check, so this is the caller's responsibility; a cross-type collision such as cAMP (metabolite) vs CAMP (gene) is out of scope. - Off by default:
harmonize(...)links bynodeandidentifieronly, exactly as before 1.5.5.
report.summary() counts links by basis (links_by_basis) and reports n_name_only_links (links
with no identifier evidence) and n_name_match_withheld, so a report can say "X linked by
identifier, Y by name only". Every link also carries bases, the full set of bases that apply.
Ambiguous links (from 1.5.6). Every link records a_partners and b_partners, how many
entities each side links to. link.ambiguous is true when either is above one: several distinct
entities landed on one entry, so the pair is a review candidate rather than a confident match.
report.one_to_one_links and report.ambiguous_links split the links, and summary() adds
n_one_to_one_links and n_ambiguous_links. All links are still returned; nothing is dropped.
On NECS x Xu et al. 2022 scored against Metabolon compound IDs, one-to-one links were 397 of 398
correct (99.7%) versus 439 of 575 (76.3%) for all links.
Identification-confidence markers (unreleased). Metabolon marks how a compound was identified
with asterisks on its name: no asterisk means confirmed with an authentic chemical standard, *
means identified with confidence but not confirmed with a standard, and ** means reasonably
identified without an available standard. Every link records each side's marker as
a_id_confidence / b_id_confidence (0, 1 or 2, read from each result's query_name; see
biomapper.harmonize.id_confidence_marker), and link.id_confidence_differs is true when they
differ, as in glyco-beta-muricholate** vs glyco-beta-muricholate. A marker is a run of one or
two asterisks that directly follows a non-space character and either ends the name or comes right
before ( (1-palmitoyl-gpi* (16:0)); any other asterisk is ignored, and when a name carries
two markers the longer one counts (1-arachidonoyl-GPC* (20:4)* is *). Names without markers
are always 0, so panels that do not use Metabolon names are unaffected; a marked name linked to an
unmarked one is flagged. link.needs_review is ambiguous or id_confidence_differs;
ambiguous and one_to_one_links keep their meaning. report.review_links lists the links that
need review, every other link is a confident match, and summary() adds n_id_confidence_differs
and n_needs_review. Name linking compares names with their asterisks intact, so a pair that
differs only in its marker links by identifier, never by name. On NECS x Xu et al. 2022 (engine
v1.2.1, 2026-11-05), 390 links need no review and 389 of them share a Metabolon compound ID;
before this flag the confident set was 399 links, 9 of them with differing markers.
Mixture names (unreleased). A name that lists alternative compounds, such as
butyrate/isobutyrate (4:0), describes a measurement that may be either compound. Linking it to
a name that does not list the same alternatives is a review candidate even when the link is
one-to-one. Every link records a_is_mixture / b_is_mixture.
biomapper.harmonize.is_mixture_name applies this rule to the whitespace-normalized, casefolded
name; any one of these makes it a mixture:
oras a word between spaces:linolenate [alpha or gamma; (18:3n3 or 6)],dihomo-linolenate (20:3n3 or n6).+with a space on each side:dimethylarginine (sdma + adma),(n(1) + n(8))-acetylspermidine(but notNAD+)./with at least three letters right before it and a letter or a locant (2-,5alpha-) right after it:butyrate/isobutyrate (4:0),2-hydroxybutyrate/2-hydroxyisobutyrate. Lipid chain notation (PC 16:0/18:1,d18:1/17:0) has a digit or)before the slash and never counts; neither does a slash before a unit word (mmol/mol) or any slash in a name containing the wordratio.- A bracketed group that is a comma-separated list of two or more lipid chains, Metabolon's
multi-isomer names:
sphingomyelin (d18:1/17:0, d17:1/18:0, d19:1/16:0). Other comma lists (androstenediol (3alpha, 17alpha) monosulfate,bilirubin (z,z)) do not count.
link.mixture (the mixture review reason) is true when the two sides differ as mixtures:
- exactly one side is a mixture (
butyrate/isobutyrate (4:0)vsbutyrate (4:0)), or - both are, and they list different alternatives (
dihomo-linolenate (20:3n3 or n6)vsdihomolinolenate (20:3n3 or 3n6)).
Two mixture names listing the same alternatives in any order are not flagged:
dimethylarginine (sdma + adma) vs dimethylarginine (adma + sdma), or the same Metabolon
multi-isomer string on both sides. The comparison uses biomapper.harmonize.mixture_alternatives_key
(stored on the link as a_mixture_key / b_mixture_key): the casefolded name without its
identification-confidence markers, with the alternatives inside each bracket level ((...) and
[...] alike) sorted. Alternatives are only reordered within their own bracket level, so moving a
shared qualifier between levels (butyrate/isobutyrate (4:0) vs isobutyrate (4:0)/butyrate)
still counts as different, which errs toward review.
The engine's own mixture flag is honoured too: engine v1.3.1 reports
lipid_resolution.name_is_mixture on lipid names (a top-level name_is_mixture is also read if a
server sends one). A True marks the name a mixture; a False does not override the name rule,
and a server without the field changes nothing. link.needs_review is now ambiguous,
id_confidence_differs or mixture; link.review_reasons names which, report.mixture_links
lists the mixture links, and summary() adds n_mixture_links. The rule is written against
Metabolon-style metabolite names.
Possible missed matches (unreleased). report.possible_missed lists every entity that ended
up in no link although its mapping already carries a review signal, so a reviewer sees it next to
the review links instead of it disappearing. Each entry (PossibleMiss) has the cohort label, key,
name, chosen_kg_id, whether it resolved, and its reasons: the mapping's chosen_kg_id_review
value (divergent_refmet, conflict_no_structure), certificate_contradicted, and/or
mixture (per entity: the entity's own name is a mixture). Errored entities are never listed. report.a_possible_missed / b_possible_missed split
it by side, and summary() adds n_possible_missed plus a possible_missed count in each cohort
block. Entries are listed per cohort; nothing pairs them across cohorts.
On NECS x Xu et al. 2022 (engine v1.3.1, offline re-score 2026-11-06), 6 links are mixture
reviews and 2 of them are flagged for that reason alone (butyrate/isobutyrate (4:0) with
butyrate (4:0), and the two linolenate spellings; both share a Metabolon compound ID). 401 links
need no review and 400 of them share a compound ID; 99 links need review. 77 entities are listed
as possible misses (68 NECS, 9 Xu), including both sides of the one Monti et al. pair BioMapper
does not link (dihomo-linolenate (20:3n3 or n6) with dihomolinolenate (20:3n3 or 3n6)).
Two rules the linker is built around:
- No structure identifiers.
INCHIKEY,INCHIandSMILESare excluded. Linking on a structure hash would make any downstream structural certificate circular and would make precision 100% by construction. - Prefix synonyms normalize.
KEGG.COMPOUND:C00031equalsKEGG:C00031; genuinely different identifier spaces such asKEGG.GLYCANstay distinct.
An entity that resolved to nothing is a refusal candidate, not a link. It is named in
a_unresolved / b_unresolved, counted in summary(), and left out of the link-rate
denominator so non-resolution is never scored as non-equivalence. An entity whose mapping call
errored is tracked separately again in a_errors / b_errors.
Import it as from biomapper.harmonize import harmonize. The name is deliberately not bound on
the package root, where it would shadow the submodule.
Harmonizing two cohorts in one call: harmonize_cohorts()
harmonize_cohorts() runs the whole protocol: it reads both cohort tables, maps them, links them
with harmonize(), and writes a pinned report. It exists because the obvious manual path can
quietly make results worse. When only one cohort publishes an identifier type, supplying it moves
that cohort onto code-specific entries the other cohort never reaches by name: on the UK Biobank x
Arivale clinical labs, supplying Arivale's LOINC codes cut matched pairs from 31 to 2.
What it does:
- Names-only arm. Both cohorts are mapped by name with the resolved category and no
identifiers.
entitytakesmetabolites(SmallMolecule),proteins(Protein),genes(Gene),labs(ClinicalMeasurement, where lab tests live in Biolink) or any rawbiolink:category;category=overrides an alias. Name linking is on for SmallMolecule only, as inharmonize(). - Identifier arm, shared vocabularies only. You declare identifier columns per vocabulary
and cohort (
{"LOINC": [...]}); names are normalized, soKEGG.COMPOUNDequalsKEGG. Only vocabularies both cohorts declare are supplied as mapping input, and only rows carrying one are re-mapped; the rest reuse their names-only result. With nothing shared the arm is skipped and the report says why; with no identifier columns only the names-only arm runs. - Review queue for one-sided codes. Each code of a vocabulary only one cohort declares is
resolved on its own (
annotation_mode="none", one request per row and code) and compared with the row's names-only entry by identifier-set intersection. Every code gets a status (agree,disagree,code_unresolved,name_unresolved_code_resolved,errored);report.review_queuelists everything butagree, with both entries. On the labs this lists Arivale "Glucose", whose name lands on one entry while its LOINC code 2345-7 says another. - Report. Both
HarmonizationResults (report.names_only,report.identifier), theirdiff(pairs found only by names, only with identifiers, by both), one-to-one and ambiguous link counts per arm (n_one_to_one_links/n_ambiguous_links, as inharmonize()), link bases, warnings, excluded rows (blank names), and pins. Each arm's link table carriesa_partners,b_partnersand aone_to_oneflag, so ambiguous links can be reviewed, plusa_id_confidence,b_id_confidence,id_confidence_differs,needs_review,a_is_mixture,b_is_mixture,mixtureandreview_reasons; each arm's summary addsn_id_confidence_differs,n_mixture_links,n_needs_reviewandn_possible_missed. Each arm also writespossible_missed_<arm>.tsv(cohort, key, name, chosen_kg_id, resolved, reasons).
Output by default. Results are written to biomapper_runs/harmonize_cohorts_<UTC stamp>/
under the current directory (override with output_dir=; save=False to skip;
report.write(path) any time): mapping results per arm and cohort, written as each arm finishes
so a failure keeps finished work, link and possible-missed tables per arm, diff.tsv,
review_queue.tsv,
settings.json and summary.json. Nothing beyond what you passed in is written, and input files
are recorded by name and SHA-256, never by absolute path.
Pins. The package version; the API's /health status and self-reported version (labelled
"self-reported, known stale": the API does not expose its engine release, which is recorded as
unavailable); Kestrel's /health kestrel_version and kg_build together with the Kestrel URL
used (kestrel_url=); and a UTC timestamp. probe_pins=False skips the two reads.
Requests. The default mapper sends batches of 10 with a 300 s timeout (batch_size=,
timeout=, progress=True to see them); a failed batch becomes errored rows that are counted,
not an exception. Pass mapper= (any (records, *, entity_type, annotation_mode) -> list[MappingResult] callable) to replay recorded results offline; the tests replay the UK Biobank
x Arivale labs this way (tests/fixtures/cohorts_labs_cm/, KRAKEN kg 2.3.0 / 3dd08a5b: 37 pairs,
21 one-to-one by name).
Use from an agent (MCP)
biomapper ships a local stdio MCP server (the biomapper
command, alias biomapper-mcp), so an agent can resolve entities through the same public, keyless API as the
Python client. It runs on your machine; nothing is hosted. Launch it with one command (needs
uv):
Claude Code (the server sees your project folder through MCP roots):
Claude Desktop (claude_desktop_config.json). Desktop does not inherit your shell PATH, so
use the absolute path that which uvx prints, and list the folders map_file may use, because
Desktop shares no project roots:
Tools
Every result says resolved, unresolved, refused, or error. An error is a failed call,
never a confirmed no-match. Results carry a compact provenance block (client version, API URL,
KG build per Kestrel /health, labeled assumed, not verified, and kg_verified).
Throughput, and why the limits exist
The hosted deployment is one shared instance that answers about 4-5 s per entity and slows sharply under concurrent load, so the server is deliberately polite:
- One request in flight per server process. Interactive calls and file-job chunks share one gate; a call that cannot get it within ~10 s returns "busy, retry shortly".
- Every tool call returns in under 60 s (Claude Desktop cancels at ~60 s), which is why
map_batchstops at 5 and long work runs as a job. - Loop guard: more than 20
map_entity/map_batchcalls in 5 minutes are refused with a pointer tomap_file. Discovery and status tools do not count.
File jobs
map_file(path, name_column, entity_type, identifier_columns?, output_path?) validates the file
(readable, columns present, rows counted, output not already there, /health answering) and
queues it. identifier_columns maps a column to its vocabulary, e.g. {"hmdb_id": "HMDB"}.
- Output:
<input>.biomapper.tsvnext to the input plus<input>.biomapper.provenance.json(full pins: API, Kestrel, KG build). It never overwrites a file. Progress is written to<output>.partialuntil the job completes. - Resumable: rows are mapped in chunks of 5 and cached as they land. If the agent session
ends, the job is
paused; the next session in the same folder resumes it automatically, without re-mapping cached rows. Jobs idle for more than 7 days becomeexpiredand resume only throughresume_job. - Honest failure: three whole-chunk failures in a row, or one chunk slower than 240 s, move the
job to
stalledand it stops sending requests;resume_jobretries after a health check. A row that errors three times is written aserror. A changed input file, or a KG build that differs from the cached rows, fails the job;rerun=truestarts over. - Folders:
map_fileonly reads and writes inside the client's MCP roots plusBIOMAPPER_MCP_ROOTS, with symlinks resolved. With neither, it refuses and says how to set them; the interactive tools still work.
Environment
On HPC or shared hosts whose home directory is on NFS/SMB, set BIOMAPPER_MCP_HOME to local disk:
job ownership uses OS file locks, which network filesystems may not honor across machines.
API reference
MappingResult
DatasetMappingResult
Return type of map_dataset_file_sync. Captures per-row results plus an
opt-in error signal for partial runs.
raise_for_error mirrors httpx.Response.raise_for_status and turns the
partial-result contract into an explicit caller opt-in — silent consumption
of a truncated run (using .results without checking .error) is the
footgun this model is designed to prevent.
Note:
confidence_scoreon dataset-stream results is alwaysNone— the/map/dataset/streamendpoint emits a slimmer per-row payload than/map/batchand does not include the annotatorassigned_idsblock. Usemap_entity/map_entitiesif you need confidence tiers.
Confidence tiers
Error handling
An authentication failure (401/403) raises BioMapperAuthError from every entry point, sync or
async, because it is systemic: every later request would fail the same way. The synchronous
map_entity and map_entities go through the batch endpoint, where transient failures (429,
5xx, timeouts, a malformed response) and per-entity problems do not raise: each affected record
comes back as MappingResult(error=...) rather than aborting the batch. Check .error on every
result. The single-entity call on the async client, await client.map_entity(...), raises the
typed exceptions (BioMapperRateLimitError, BioMapperServerError, BioMapperTimeoutError)
directly.
Dataset streaming (map_dataset_file_sync) uses a two-tier contract:
- Initial-request errors (401, 422, 500, connect timeout) raise as typed exceptions — these happen before any row is processed, so partial results don't exist to preserve.
- Mid-stream transport failures are captured into
DatasetMappingResult.errorwith the partial results preserved in.results. Call.raise_for_error()to get exception semantics, or inspect.errordirectly for "accept partial, log the rest" workflows.
Callback exceptions raised from on_result propagate unwrapped and
replace the return value — partial results collected up to that point
are lost. For UI consumers with failure-prone callbacks, wrap the callback
body in your own try/except if you want partial data to survive.
External benchmark suite
An API-only reproduction harness for the benchmarks the BioMapper preprint reports. It runs against a deployment, not a local engine checkout, which matters for two reasons: running in-process against a checkout measures a library rather than the deployed service, and pointing at a deployment pins provenance to the backend that actually served the answers.
The public KRAKEN endpoint is keyless, and a BioMapper2 deployment with no keys configured is
open, so the suite runs unauthenticated by default. Set BIOMAPPER_API_KEY if your deployment
requires one; the key is never accepted on the command line, because argv is visible to other
processes and lands in shell history.
The arms
Read the Reportable as column before quoting anything. Four of the graph's ingested sources
(lipidmaps, refmet, loinc, ncbigene) are gold sources for arms above, so those arms measure
coverage, not independent accuracy: the gold identifier and BioMapper's answer come from the same
place. Each run labels every arm from the build's own source list rather than from a static note,
so the label tracks the graph.
Two further reporting rules the suite enforces rather than documents:
- Gene arms report accuracy per target namespace. The any-namespace roll-up is emitted flagged
quotable: false, because the namespaces perform very differently and the roll-up has been quoted as though it described all of them. - A skipped arm is not a zero and not a pass. It carries a reason into the manifest.
Provenance
Every run records what actually served it, read from Kestrel /health (keyless) rather than
hardcoded: kestrel_version, kg_version, biolink_version, build_timestamp, git_commit, the
full source_versions map, the package version, each dataset's source SHA, and a run id. The build
is read once before the arms start and re-read afterwards; if it moved mid-suite, the manifest says
so, because the pins would no longer describe every number.
Results are saved by default to a timestamped directory (override with --out). There is no flag
that discards them: the expensive part of a run is live API traffic.
What stayed in the engine repo
The CI regression gates (gate.py, conflation_gate.py, test_regression_gate.py,
kg-regression.yml) guard merges and need engine internals. The --resolver-mode {weighted,vote}
A/B toggles a resolver constructor argument that is deliberately not on the API surface.
Development
docs/solutions/ holds documented solutions to past problems — bugs, best practices, and workflow
patterns — organized by category with YAML frontmatter (module, tags, problem_type). Relevant
when implementing or debugging in an area something has already been written about.
License
MIT — see LICENSE.
Related
- BioMapper2 API:
https://biomapper.expertintheloop.io
来源:README.md,提交 603b86b
工具
0版本历史
2- v1.6.3最新Nov 7, 2026
- v1.6.2Nov 5, 2026
评分
已满足适用检查项的 50%
该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。
- 近 30 天内可连通25 分
请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。
- 已声明认证方式10 分
请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。
- 已列出工具15 分
请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。
- 描述必需15 分
- 图标10 分
- 文档15 分
- 许可证10 分