opencode-bioresearcher 1.11.1 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +110 -49
- package/agents/bioresearcher-dr-worker.md +32 -20
- package/connector-meta.json +6 -5
- package/index.js +146 -61
- package/package.json +4 -2
- package/skill-bundle.json +3 -5
- package/skills/bioresearcher-deep-research/SKILL.md +4 -4
- package/skills/bioresearcher-deep-research/references/article-literature.md +36 -18
- package/skills/bioresearcher-deep-research/references/diseases.md +1 -1
- package/skills/bioresearcher-deep-research/references/drugs.md +5 -4
- package/skills/bioresearcher-deep-research/references/functional-genomics.md +7 -3
- package/skills/bioresearcher-deep-research/references/genes.md +5 -3
- package/skills/bioresearcher-deep-research/references/patents.md +9 -3
- package/skills/bioresearcher-deep-research/references/rate-limiting-auth.md +7 -2
- package/skills/bioresearcher-deep-research/references/tool-selection.md +8 -5
- package/skills/bioresearcher-deep-research/references/utility-config.md +2 -2
- package/skills/bioresearcher-onboard/SKILL.md +114 -0
- package/skills/bioresearcher-onboard/scripts/bootstrap.ps1 +96 -0
- package/skills/bioresearcher-onboard/scripts/bootstrap.sh +127 -0
- package/skills/bioresearcher-onboard/scripts/onboard.mjs +512 -0
- package/loader.js +0 -3
|
@@ -5,10 +5,11 @@ Literature search and retrieval via `article_search` / `article_get`
|
|
|
5
5
|
|
|
6
6
|
## Overview
|
|
7
7
|
|
|
8
|
-
`article_search` runs federated search across up to
|
|
9
|
-
deduplication; `article_get` retrieves one article by PMID/PMCID/DOI
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
`article_search` runs federated search across up to six backends with
|
|
9
|
+
deduplication; `article_get` retrieves one article by PMID/PMCID/DOI (journal
|
|
10
|
+
or preprint DOI) with optional annotations, citation graphs, and opt-in
|
|
11
|
+
full text. `article_search` enforces a 30-second execution timeout,
|
|
12
|
+
`article_get` 60 seconds.
|
|
12
13
|
|
|
13
14
|
## Tools
|
|
14
15
|
|
|
@@ -17,10 +18,10 @@ enforce a 30-second execution timeout.
|
|
|
17
18
|
| Parameter | Type | Notes |
|
|
18
19
|
|-----------|------|-------|
|
|
19
20
|
| query | string (required) | Search query (title, abstract, or keyword) |
|
|
20
|
-
| source | enum, optional | `pubmed`, `europepmc`, `semantic_scholar`, `pubtator`, `litsense`; omit for federated search
|
|
21
|
+
| source | enum, optional | `pubmed`, `europepmc`, `semantic_scholar`, `pubtator`, `litsense`, `preprint_only`, `arxiv`; omit for federated search (bioRxiv/medRxiv preprints are NOT included unless `preprint_only` is explicit; the default federation does include the `arxiv` leg) |
|
|
21
22
|
| limit | int 1-50, default 10 | Applied to FINAL deduplicated results, not per-source |
|
|
22
23
|
| offset | int >= 0, default 0 | Result offset |
|
|
23
|
-
| dateRange | string, optional | `YYYY-MM-DD/YYYY-MM-DD`; open-ended `2020-01-01/` or `/2023-12-31`; at least one endpoint required.
|
|
24
|
+
| dateRange | string, optional | `YYYY-MM-DD/YYYY-MM-DD`; open-ended `2020-01-01/` or `/2023-12-31`; at least one endpoint required. Supported by `pubmed`, `europepmc`, `semantic_scholar`, `preprint_only`, `arxiv` - NOT `pubtator`/`litsense` |
|
|
24
25
|
|
|
25
26
|
Federated sources at a glance:
|
|
26
27
|
|
|
@@ -31,20 +32,34 @@ Federated sources at a glance:
|
|
|
31
32
|
| semantic_scholar | CS/ML-adjacent and citation graph (key optional) |
|
|
32
33
|
| pubtator | Biomedical entity-tagged (gene/disease/drug/variant/chemical) |
|
|
33
34
|
| litsense | Sentence-level semantic match to the query |
|
|
35
|
+
| preprint_only | bioRxiv/medRxiv preprints only (rows carry `preprint_server`, `ppr_id`) |
|
|
36
|
+
| arxiv | arXiv preprint server (rows carry `arxiv_id`) |
|
|
34
37
|
|
|
35
38
|
### article_get
|
|
36
39
|
|
|
37
40
|
| Parameter | Type | Notes |
|
|
38
41
|
|-----------|------|-------|
|
|
39
|
-
| id | string (required) | PMID (numeric, e.g. "12345"), PMCID ("PMC1234567"),
|
|
40
|
-
| sections | enum array, optional | `core`, `oa`, `annotations`, `graph`, `citation`, `all`; omit for core metadata only |
|
|
42
|
+
| id | string (required) | PMID (numeric, e.g. "12345"), PMCID ("PMC1234567"), journal DOI ("10.1038/s41586-021-03819-2"), or preprint DOI ("10.1101/YYYY.MM.NN.NNNNNN", new prefix "10.64898/...") |
|
|
43
|
+
| sections | enum array, optional | `core`, `oa`, `fulltext`, `annotations`, `graph`, `citation`, `all`; omit for core metadata only. `["all"]` = oa+annotations+graph+citation WITHOUT fulltext - request `["fulltext"]` separately |
|
|
41
44
|
| limit | int 1-100, default 20 | Max items per section (e.g. 20 citations) |
|
|
42
45
|
| citation_mode | `fast` (default) / `full` | fast ~4 s, 4 providers with auto-fallback to PubMed; full ~15-30 s, all 5 providers incl. PubMed |
|
|
43
46
|
| citation_direction | `forward` / `backward` / `both` (default) | forward = articles citing this one; backward = its references |
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
47
|
+
| fulltext_output | `file` (default) / `inline` | `sections:["fulltext"]` output mode - see below |
|
|
48
|
+
| fulltext_max_chars | int 1000-200000, default 40000 | Inline-mode only cap for `fulltext` text; ignored in file mode |
|
|
49
|
+
|
|
50
|
+
Section contents: `core` = title/authors/journal/abstract; `oa` =
|
|
51
|
+
license/access metadata and links ONLY - status vocabulary
|
|
52
|
+
`open_access | free_to_read | paywalled | not_in_pmc | unknown` (a pdf_url
|
|
53
|
+
does not by itself mean the text is fetchable); `fulltext` = the ACTUAL
|
|
54
|
+
text when freely readable in PMC/Europe PMC (opt-in, never triggered by
|
|
55
|
+
`"all"`); `annotations` = PubTator entity annotations; `graph` = citation
|
|
56
|
+
graph; `citation` = forward citations + backward references.
|
|
57
|
+
|
|
58
|
+
`fulltext` is file-first: by default the complete text is written to a
|
|
59
|
+
server-side markdown file and the reply carries `file_path` plus an outline
|
|
60
|
+
(Read/Grep the file selectively). Use `fulltext_output: "inline"` (capped by
|
|
61
|
+
`fulltext_max_chars`) only when the harness cannot read server-side files.
|
|
62
|
+
`oa`/`fulltext` do not apply to preprint DOIs.
|
|
48
63
|
|
|
49
64
|
## Worked examples
|
|
50
65
|
|
|
@@ -74,25 +89,28 @@ Full metadata plus citations for a known PMID:
|
|
|
74
89
|
| Symptom | Cause | Fix |
|
|
75
90
|
|---------|-------|-----|
|
|
76
91
|
| Tool error "timed out after 30000ms" | federated fan-out exceeded 30 s | retry with a single `source`, narrower `dateRange`, or `limit` lowered |
|
|
77
|
-
| dateRange silently ignored | `source` was pubtator or litsense | filter dates client-side, or switch source to pubmed/europepmc/semantic_scholar |
|
|
92
|
+
| dateRange silently ignored | `source` was pubtator or litsense | filter dates client-side, or switch source to pubmed/europepmc/semantic_scholar/arxiv/preprint_only |
|
|
78
93
|
| Fewer results than limit on federated search | dedup-then-limit semantics | page with `offset`; duplicates across sources collapse into one entry |
|
|
79
94
|
| citation section empty in fast mode | providers returned no items (fast auto-falls back to PubMed) | retry with `citation_mode: "full"` |
|
|
80
95
|
|
|
81
|
-
## Field contract (biomcp >= 1.
|
|
96
|
+
## Field contract (biomcp >= 1.6.0)
|
|
82
97
|
|
|
83
98
|
Article records from every article tool path (`article_search`,
|
|
84
99
|
`article_get`, `batch_get`, `discover`) carry: `pmid`, `pmcid`, `doi`,
|
|
85
100
|
`title`, `authors` (full "LastName ForeName" strings - Vancouver initials are
|
|
86
|
-
computed by the evidence-ledger `bib` command), `journal`, `
|
|
87
|
-
(raw string), `volume`, `issue`, `pages` (null when the
|
|
88
|
-
none, e.g. epub-ahead-of-print), plus `mesh_headings
|
|
89
|
-
`keywords`/`chemicals` on PubMed paths. HTML entities are
|
|
101
|
+
computed by the evidence-ledger `bib` command), `journal`, `journal_issn`,
|
|
102
|
+
`publication_date` (raw string), `volume`, `issue`, `pages` (null when the
|
|
103
|
+
upstream record has none, e.g. epub-ahead-of-print), plus `mesh_headings`/
|
|
104
|
+
`publication_types`/`keywords`/`chemicals` on PubMed paths. HTML entities are
|
|
105
|
+
decoded to UTF-8.
|
|
90
106
|
|
|
91
107
|
Backend coverage notes:
|
|
92
108
|
|
|
93
109
|
- Only `pubmed` and `europepmc` return locator fields (volume/issue/pages).
|
|
94
110
|
- `semantic_scholar`, `pubtator`, and `litsense` records never carry
|
|
95
111
|
locators.
|
|
112
|
+
- `preprint_only` rows carry `preprint_server`/`ppr_id` and `arxiv` rows
|
|
113
|
+
carry `arxiv_id`; neither carries journal locator fields.
|
|
96
114
|
- LitSense hits are HINT records: `{pmid, pmcid, score, source}` only - no
|
|
97
115
|
title, no abstract. Before citing a LitSense-only PMID, enrich it with
|
|
98
116
|
`article_get(pmid)` (one sequential call; standard retry ladder on
|
|
@@ -80,7 +80,7 @@ Trial landscape directly (name accepted):
|
|
|
80
80
|
|
|
81
81
|
| Symptom | Cause | Fix |
|
|
82
82
|
|---------|-------|-----|
|
|
83
|
-
| `_error: Disease
|
|
83
|
+
| `_error: Disease 'X' not found. Try disease_search...` from disease_trials | invalid/unresolvable ID | call `disease_search` first and copy the exact ID; supported formats are MONDO/DOID/OMIM/UMLS CUI (message text) plus EFO/Orphanet accepted by the resolver |
|
|
84
84
|
| disease_get 0 hits for a raw name | the tool wants an ID, not a name | resolve via `disease_search`, or use `disease_trials`/`disease_drugs` which accept names |
|
|
85
85
|
| Sections empty | over-narrow section set or sparse annotation for rare diseases | try `sections: ["all"]` and note data sparsity in the report |
|
|
86
86
|
|
|
@@ -6,7 +6,7 @@ Drug identity, regulatory status, labels, adverse events, and targets via
|
|
|
6
6
|
## Overview
|
|
7
7
|
|
|
8
8
|
`drug_search` finds drugs by name/mechanism/keyword (MyChem-backed);
|
|
9
|
-
`drug_get` returns per-drug detail with sections spanning US/
|
|
9
|
+
`drug_get` returns per-drug detail with sections spanning US/WHO
|
|
10
10
|
regulatory data, FDA labels (safety), FAERS adverse events, targets, and
|
|
11
11
|
indications; `drug_trials` cross-links to clinical trials.
|
|
12
12
|
|
|
@@ -25,7 +25,7 @@ indications; `drug_trials` cross-links to clinical trials.
|
|
|
25
25
|
| Parameter | Type | Notes |
|
|
26
26
|
|-----------|------|-------|
|
|
27
27
|
| name | string (required) | Drug name, e.g. "imatinib", "aspirin" |
|
|
28
|
-
| sections | enum array, optional | `core`, `us_regulatory`, `
|
|
28
|
+
| sections | enum array, optional | `core`, `us_regulatory`, `who_regulatory`, `safety`, `targets`, `indications`, `adverse_events`, `all` |
|
|
29
29
|
| limit | int 1-100, default 20 | For `adverse_events`, caps the number of ranked reaction rows |
|
|
30
30
|
|
|
31
31
|
Section semantics (important - commonly confused):
|
|
@@ -34,7 +34,7 @@ Section semantics (important - commonly confused):
|
|
|
34
34
|
|---------|----------|
|
|
35
35
|
| core | identity, identifiers, description |
|
|
36
36
|
| us_regulatory | US brand name + `fda_status` (e.g. approved) - NOT full labels, NOT approval history |
|
|
37
|
-
|
|
|
37
|
+
| who_regulatory | WHO Prequalification products: `{prequalified, products, note}` - prequalification listing, not regulatory summaries |
|
|
38
38
|
| safety | FDA LABEL TEXT: box_warning, warnings, adverse_reactions - this is where label prose lives |
|
|
39
39
|
| adverse_events | FDA FAERS adverse reactions RANKED by report count - no filters (no patient age/sex/date/reaction filtering) |
|
|
40
40
|
| targets | drug targets |
|
|
@@ -65,7 +65,7 @@ Regulatory snapshot + targets + indications in one call:
|
|
|
65
65
|
|
|
66
66
|
```json
|
|
67
67
|
{"name": "trastuzumab",
|
|
68
|
-
"sections": ["us_regulatory", "
|
|
68
|
+
"sections": ["us_regulatory", "who_regulatory", "targets", "indications"]}
|
|
69
69
|
```
|
|
70
70
|
|
|
71
71
|
## Failure modes
|
|
@@ -75,6 +75,7 @@ Regulatory snapshot + targets + indications in one call:
|
|
|
75
75
|
| us_regulatory is surprisingly thin | it only carries brand name + fda_status | label text (warnings, box warning, adverse reactions) is in `safety` |
|
|
76
76
|
| Wanting FAERS filtered by age/sex/date | `adverse_events` exposes ranked counts only - no filters | take the ranked list and note the limitation in the report; do not claim subgroup-level FAERS results |
|
|
77
77
|
| 0 hits for a trade name | search index prefers generic/mechanism terms | `drug_search` by generic name or mechanism, then `drug_get` by the matched name |
|
|
78
|
+
| `sections: ["eu_regulatory"]` rejected (MCP -32602) | `eu_regulatory` was removed in biomcp 1.6.0 | drop it; US status is `us_regulatory`, WHO prequalification is `who_regulatory` |
|
|
78
79
|
| Payload too large | `sections: ["all"]` on a heavily annotated drug | request only the needed sections; lower `limit` for reaction rows |
|
|
79
80
|
|
|
80
81
|
## Integration notes
|
|
@@ -44,9 +44,13 @@ not index them; the error points at ENA (https://www.ebi.ac.uk/ena).
|
|
|
44
44
|
`format` (`genbank` default / `fasta`), `seq_start`/`seq_stop` (1-based
|
|
45
45
|
inclusive region), `strand` (1 plus; 2 minus, allows seq_start > seq_stop for
|
|
46
46
|
reverse slices), `max_response_bytes` (default 30,000,000; oversized errors
|
|
47
|
-
rather than truncates)
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
rather than truncates), `sequence_output` (`file` default / `inline`). Caps:
|
|
48
|
+
whole-record fetches max 2,000,000 bp - larger records REQUIRE a
|
|
49
|
+
seq_start/seq_stop region (up to 10 Mb span). Sequences over 1,000 characters
|
|
50
|
+
default to FILE mode: the full text is written to a server-side cache file
|
|
51
|
+
and the reply carries `file_path` + char counts (never truncated) - Read/Grep
|
|
52
|
+
the file selectively. `sequence_output: "inline"` opts back into inline
|
|
53
|
+
`sequence_text`, capped at its first 200,000 characters.
|
|
50
54
|
|
|
51
55
|
`genbank_genes`: maps a nucleotide accession to NCBI Gene IDs (elink
|
|
52
56
|
nuccore->gene) usable directly with gene_get/gene_search (entrezgene IDs) -
|
|
@@ -40,11 +40,11 @@ Protein Atlas - see pacing note below), `druggability` (DGIdb),
|
|
|
40
40
|
|
|
41
41
|
| Tool | Parameters | Notes |
|
|
42
42
|
|------|-----------|-------|
|
|
43
|
-
| gene_diseases | symbol, limit (1-50, default 10) | DisGeNET associations NEED `DISGENET_API_KEY`; without it the tool
|
|
43
|
+
| gene_diseases | symbol, limit (1-50, default 10) | DisGeNET associations NEED `DISGENET_API_KEY`; without it the tool silently returns OpenTargets gene-disease rows (source: "opentargets") |
|
|
44
44
|
| gene_drugs | symbol | Drugs targeting the gene |
|
|
45
45
|
| gene_trials | symbol | Clinical trials referencing the gene |
|
|
46
46
|
| gene_articles | symbol | Articles about the gene (relevance search, no recency sort) |
|
|
47
|
-
| gene_enrich | genes (
|
|
47
|
+
| gene_enrich | genes (min 3 HGNC symbols), limit (1-100, default 30) | Reactome pathway enrichment; success returns `{pathways, total_reported, truncated}`; a single `_error` row on failure |
|
|
48
48
|
|
|
49
49
|
## Worked examples
|
|
50
50
|
|
|
@@ -77,7 +77,7 @@ Enrichment on a hit list:
|
|
|
77
77
|
| Symptom | Cause | Fix |
|
|
78
78
|
|---------|-------|-----|
|
|
79
79
|
| gene_get error: not a valid HGNC symbol | alias or outdated name used | pass the official symbol, or set `smart: true` |
|
|
80
|
-
| gene_diseases returns `_error`
|
|
80
|
+
| gene_diseases returns an `_error` row | BOTH DisGeNET and OpenTargets failed - not merely a missing key | without `DISGENET_API_KEY` the tool silently returns OpenTargets rows (source: "opentargets"); add the key for DisGeNET-grade associations and retry transient backend failures |
|
|
81
81
|
| HPA sections slow/erroring when iterating many genes | `protein_atlas`/`expression` use an unthrottled raw fetch | pace these calls manually; other sections are server-limited |
|
|
82
82
|
| gene_enrich single `_error` row | Reactome AnalysisService rejected the input | check symbols are valid HGNC; retry with a smaller list |
|
|
83
83
|
|
|
@@ -90,4 +90,6 @@ Enrichment on a hit list:
|
|
|
90
90
|
gene expression questions with tissue profiles.
|
|
91
91
|
- `ensembl_lookup` (references/ensembl-pdb.md) is the identifier/structure
|
|
92
92
|
authority (stable IDs, coordinates, transcripts) for ANY Ensembl species.
|
|
93
|
+
- `gene_enrich` runs 15-45 s typically (~105 s worst case, its server-side
|
|
94
|
+
budget) - keep client tool timeouts generous (>= 120 s) for it.
|
|
93
95
|
- MyGene is server-limited at 100 ms - no manual throttling.
|
|
@@ -29,7 +29,12 @@ the biomedical ones: search is bounded at 60 s, detail at 120 s.
|
|
|
29
29
|
| seminal | boolean, optional, default true | Co-citation mining of top results to surface foundational prior art in `seminal_prior_art`; adds ~5-30 s - set `false` for the fastest bibliographic lookups |
|
|
30
30
|
|
|
31
31
|
Default (no `source`) "auto" mode: queries worldwide + ppubs concurrently; if
|
|
32
|
-
ppubs fails hard it falls back to uspto_odp once (
|
|
32
|
+
ppubs fails hard it falls back to uspto_odp once (noted in `warnings`). The
|
|
33
|
+
success payload is an envelope: `{patents, total_hits, total_hits_basis,
|
|
34
|
+
seminal_prior_art, mined_count, errors?, warnings?}` - backend failures
|
|
35
|
+
(e.g. a google_patents timeout) ride in `errors` as `{source, message}`
|
|
36
|
+
entries, fallback/coverage notes in `warnings`; there are no in-band marker
|
|
37
|
+
rows inside `patents`.
|
|
33
38
|
|
|
34
39
|
### patent_get
|
|
35
40
|
|
|
@@ -82,8 +87,9 @@ Pull claims and citations for a specific patent:
|
|
|
82
87
|
|
|
83
88
|
## Integration notes
|
|
84
89
|
|
|
85
|
-
- Auto-mode
|
|
86
|
-
|
|
90
|
+
- Auto-mode envelope fields flag data lineage - `errors[]` entries
|
|
91
|
+
(source + message) record backend failures and `warnings[]` records
|
|
92
|
+
fallback/coverage notes; mention them in the report when present.
|
|
87
93
|
- EPO OPS and USPTO are server-limited at ~1 s token buckets - no manual
|
|
88
94
|
throttling; expect patent tools to be the slowest calls in an aspect.
|
|
89
95
|
- Cite patents by publication number with a Google Patents or Espacenet URL
|
|
@@ -49,7 +49,11 @@ Everything else: call sequentially, no timers.
|
|
|
49
49
|
|
|
50
50
|
| Tool | Budget |
|
|
51
51
|
|------|--------|
|
|
52
|
-
| article_search /
|
|
52
|
+
| article_search / journal_metrics | 30 s |
|
|
53
|
+
| article_get | 60 s |
|
|
54
|
+
| gene_get / disease_get / drug_get / variant_get / pdb | 40 s |
|
|
55
|
+
| trial_get / variant_trials | 45 s |
|
|
56
|
+
| gene_enrich | up to ~105 s (keep client tool timeouts >= 120 s) |
|
|
53
57
|
| patent_search | 60 s |
|
|
54
58
|
| patent_get | 120 s |
|
|
55
59
|
| Per-source HTTP timeout (most sources) | 15 s |
|
|
@@ -75,6 +79,7 @@ Everything else: call sequentially, no timers.
|
|
|
75
79
|
| `CROSSREF_EMAIL` | Crossref polite pool - faster citation metadata |
|
|
76
80
|
| `EPO_OPS_CONSUMER_KEY` + `EPO_OPS_CONSUMER_SECRET` | EPO OPS patent backend: worldwide search + EP/WO claims (BOTH must be set together) |
|
|
77
81
|
| `USPTO_API_KEY` | USPTO Open Data Portal application search backend |
|
|
82
|
+
| `OPENALEX_API_KEY` | `journal_metrics`: private per-key daily budget instead of the shared keyless OpenAlex pool (free key at openalex.org) |
|
|
78
83
|
|
|
79
84
|
Set keys in the MCP client's env block (opencode: `environment`; Claude/
|
|
80
85
|
Codex: `env`), then restart the client - config changes never apply live.
|
|
@@ -84,7 +89,7 @@ Codex: `env`), then restart the client - config changes never apply live.
|
|
|
84
89
|
- Patents: US search works keyless via USPTO Public Search (ppubs default US
|
|
85
90
|
backend); Google Patents is a best-effort fallback.
|
|
86
91
|
- Drug regulatory/FAERS data works keyless (lower limits).
|
|
87
|
-
- Literature works keyless across all
|
|
92
|
+
- Literature works keyless across all six federated sources.
|
|
88
93
|
|
|
89
94
|
## Integration notes
|
|
90
95
|
|
|
@@ -5,10 +5,11 @@ Route a research question to the correct biomcp tool, then shape the call with
|
|
|
5
5
|
|
|
6
6
|
## Overview
|
|
7
7
|
|
|
8
|
-
biomcp (npm `biomcp`, pinned `biomcp@1.
|
|
9
|
-
environment-gated optional tools (3 database, 4 R analysis, 8 biowasm).
|
|
10
|
-
|
|
11
|
-
domain
|
|
8
|
+
biomcp (npm `biomcp`, pinned `biomcp@1.6`) exposes 58 tools: 43 core plus 15
|
|
9
|
+
environment-gated optional tools (3 database, 4 R analysis, 8 biowasm). The
|
|
10
|
+
1.6 core set adds `journal_metrics` and `preprint_fulltext` to the article
|
|
11
|
+
family. This file routes question types to tools; per-domain parameter
|
|
12
|
+
detail lives in the domain reference files.
|
|
12
13
|
|
|
13
14
|
> In MCP clients that prefix server tools (e.g. opencode with server name
|
|
14
15
|
> 'biomcp'), tools appear as biomcp_article_search etc.
|
|
@@ -20,6 +21,8 @@ QUESTION TYPE
|
|
|
20
21
|
├─ Literature / papers / PubMed
|
|
21
22
|
│ → article_search (query, source?, dateRange?, limit, offset)
|
|
22
23
|
│ → article_get (id: PMID/PMCID/DOI, sections?, citation_mode?)
|
|
24
|
+
│ → preprint_fulltext (bioRxiv/medRxiv preprint DOI, version?) # on-demand full text; license disclosed
|
|
25
|
+
│ → journal_metrics (journal name / NLM abbreviation / ISSN, limit <= 25) # OpenAlex venue quality (2-yr citedness, h-index, i10, OA) before citing
|
|
23
26
|
│ → details: references/article-literature.md
|
|
24
27
|
│
|
|
25
28
|
├─ Clinical trials / NCT IDs
|
|
@@ -131,7 +134,7 @@ Question: "What evidence links BRAF V600E to melanoma drug resistance?"
|
|
|
131
134
|
|---------|-------|-----|
|
|
132
135
|
| `no_such_tool` for a db/analysis tool | feature not enabled, or enabled after server start (tools register at startup only) | set `DB_TYPE`/`ANALYSIS_R`/`ANALYSIS_BIOWASM` in the client env block, restart the client |
|
|
133
136
|
| Tool error mentioning OncoKB token | `variant_oncokb` without `ONCOKB_TOKEN` | get a token (oncokb.org registration) and set it, or skip OncoKB |
|
|
134
|
-
| gene_diseases returns an `_error`
|
|
137
|
+
| gene_diseases returns an `_error` row | BOTH DisGeNET and OpenTargets failed - not merely a missing key | without `DISGENET_API_KEY` the tool silently returns OpenTargets rows (source: "opentargets"); add the key for DisGeNET-grade associations |
|
|
135
138
|
| variant_search returns nothing for "BRAF V600E" as `query` | compound free text is not a variant ID | use `gene="BRAF"`, `hgvsp="V600E"` as separate params (the tool also auto-splits a bare "GENE V600E" query, but explicit params are reliable) |
|
|
136
139
|
| Trial pages repeat or skip | offset paging used on trial_search | use `page_token` cursor paging |
|
|
137
140
|
|
|
@@ -104,13 +104,13 @@ Check a feature's parameters in detail:
|
|
|
104
104
|
| `no_such_tool` after enabling a feature | tools register at server start only | restart the client/session, then verify with `biomcp_configure` `{}` (`running_now`) |
|
|
105
105
|
| set refused: "sensitive" | sensitive key class requires confirmation | re-send identical call with `confirm_sensitive: true` |
|
|
106
106
|
| `cwd_refused` | server cwd is / or $HOME | use the client env block (error carries the translation) |
|
|
107
|
-
| batch_get item row contains `
|
|
107
|
+
| batch_get item row contains `success: false` + `error` | that single ID failed (typo, unknown ID) | fix the ID and re-request just that item; the batch continues and other items succeeded |
|
|
108
108
|
|
|
109
109
|
## Integration notes
|
|
110
110
|
|
|
111
111
|
- Smoke-test sequence for a fresh setup: `biomcp_configure` with `{}` ->
|
|
112
112
|
confirm expected features `running_now` -> one cheap domain call.
|
|
113
|
-
- `doctor` CLI complements this: `npx -y biomcp@1.
|
|
113
|
+
- `doctor` CLI complements this: `npx -y biomcp@1.6 doctor` (exit 0 = clear);
|
|
114
114
|
`--client opencode` emits a paste-ready client entry.
|
|
115
115
|
- Multi-entity literature pulls (e.g. 10 PMIDs from article_search) belong in
|
|
116
116
|
ONE `batch_get` call, not 10 article_get calls.
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: bioresearcher-onboard
|
|
3
|
+
description: "Bootstraps a project-local biomcp MCP server runtime in .bioresearcher-runtime/: downloads portable Node.js 22 (if missing), vendors biomcp with fast mirror support (official or npmmirror), configures optional features (R, Biowasm, SQLite), and registers the server in OpenCode, Claude Code, Cursor, ZCode, Pi, CodeBuddy, or WorkBuddy. Use when biomcp is not installed, when biomedical tools are missing, or on requests like setup bioresearcher, install biomcp, or onboard."
|
|
4
|
+
license: Apache-2.0
|
|
5
|
+
compatibility: "Unix-like shells (Linux, macOS) and Windows (PowerShell, cmd.exe); OpenCode, Claude Code, Cursor, ZCode, Pi Coding Agent, CodeBuddy, WorkBuddy"
|
|
6
|
+
metadata:
|
|
7
|
+
version: "1.2.0"
|
|
8
|
+
source: "bioresearcher-skills"
|
|
9
|
+
allowed-tools: Bash Read Write Edit
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# BioMCP Project-Local Onboarding
|
|
13
|
+
|
|
14
|
+
This skill sets up a self-contained, project-local BioMCP runtime in your
|
|
15
|
+
working directory under `.bioresearcher-runtime/`.
|
|
16
|
+
|
|
17
|
+
## What it does
|
|
18
|
+
|
|
19
|
+
- Checks if the host has Node.js >= 22.13. If missing, downloads a pinned,
|
|
20
|
+
cryptographically verified portable Node.js LTS binary into
|
|
21
|
+
`.bioresearcher-runtime/node/` (zero global installation, does not touch `~`
|
|
22
|
+
or `/usr/local`).
|
|
23
|
+
- Auto-detects network conditions (official distribution vs. fast npmmirror in
|
|
24
|
+
mainland China).
|
|
25
|
+
- Installs `biomcp` locally into `.bioresearcher-runtime/node_modules/` with
|
|
26
|
+
sub-100ms startup latency and offline resilience.
|
|
27
|
+
- Configures optional features (R analysis, Biowasm genomics, SQLite database)
|
|
28
|
+
and registers the server in your harness configuration (`opencode.json`
|
|
29
|
+
under the canonical `mcp.servers.biomcp` key, `.mcp.json`, etc.) without
|
|
30
|
+
overwriting existing settings.
|
|
31
|
+
- Verifies the configuration using the built-in diagnostic doctor.
|
|
32
|
+
|
|
33
|
+
## Steps
|
|
34
|
+
|
|
35
|
+
Follow the steps below in order.
|
|
36
|
+
|
|
37
|
+
### Step 1: Run Stage 0 Bootstrap
|
|
38
|
+
|
|
39
|
+
Execute the bootstrap script corresponding to your operating system.
|
|
40
|
+
|
|
41
|
+
**For Unix-like shells (Linux, macOS, Git Bash):**
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
bash skills/bioresearcher-onboard/scripts/bootstrap.sh
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
**For Windows (PowerShell):**
|
|
48
|
+
|
|
49
|
+
```powershell
|
|
50
|
+
powershell -NoProfile -ExecutionPolicy Bypass -File skills\bioresearcher-onboard\scripts\bootstrap.ps1
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The script automatically:
|
|
54
|
+
1. Reuses your host Node.js if version >= 22.13 is available.
|
|
55
|
+
2. If missing, downloads and verifies the official portable Node.js archive into
|
|
56
|
+
`.bioresearcher-runtime/node/`.
|
|
57
|
+
3. Installs `biomcp@1.6.0` into `.bioresearcher-runtime/node_modules/`.
|
|
58
|
+
4. Updates your harness configuration (`opencode.json` or `.mcp.json`) with
|
|
59
|
+
absolute executable paths.
|
|
60
|
+
|
|
61
|
+
### Step 2: Configure Optional Features (Optional)
|
|
62
|
+
|
|
63
|
+
By default, the core biomedical tools (PubMed/literature, clinical trials,
|
|
64
|
+
genes, variants, drugs, diseases, patents) and built-in SQLite are installed.
|
|
65
|
+
|
|
66
|
+
If the user needs specialized capabilities, pass the corresponding flags to the
|
|
67
|
+
bootstrap script or set environment variables before running:
|
|
68
|
+
|
|
69
|
+
- **R / Bioconductor Analysis** (DESeq2, edgeR, limma; requires ~2 GB RAM):
|
|
70
|
+
Pass `--with-r` to install the `webr@0.6` peer dependency and enable R
|
|
71
|
+
analysis in `.biomcp.json`.
|
|
72
|
+
- **Biowasm Analysis** (SAM/BAM/BED/BCF genomics tools):
|
|
73
|
+
Pass `--with-biowasm` to enable Biowasm in `.biomcp.json`.
|
|
74
|
+
- **Local SQLite Database**:
|
|
75
|
+
Pass `--sqlite-path=<path_to_db>` (e.g. `--sqlite-path=data/research.db`).
|
|
76
|
+
- **Client Override**:
|
|
77
|
+
Pass `--client=opencode`, `--client=claude-code`, `--client=cursor`,
|
|
78
|
+
`--client=zcode`, `--client=pi`, `--client=codebuddy`, or
|
|
79
|
+
`--client=workbuddy` if auto-detection should be overridden.
|
|
80
|
+
|
|
81
|
+
Example with R analysis and SQLite enabled:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
bash skills/bioresearcher-onboard/scripts/bootstrap.sh --with-r --sqlite-path=data/research.db
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### Step 3: In-Session Feature Reconfiguration
|
|
88
|
+
|
|
89
|
+
Once BioMCP is registered and running, you do not need to hand-edit
|
|
90
|
+
configuration files. Use the built-in `biomcp_configure` tool to inspect or
|
|
91
|
+
adjust features dynamically:
|
|
92
|
+
|
|
93
|
+
- Inspect feature status:
|
|
94
|
+
`biomcp_configure(action="status")`
|
|
95
|
+
- Enable or disable features:
|
|
96
|
+
`biomcp_configure(action="set", values={"features.analysis_r.enabled": true})`
|
|
97
|
+
- Configure SQLite database:
|
|
98
|
+
`biomcp_configure(action="set", values={"features.database.enabled": true, "features.database.type": "sqlite", "features.database.sqlite_path": "data/research.db"}, confirm_sensitive=true)`
|
|
99
|
+
|
|
100
|
+
### Step 4: Restart the Harness
|
|
101
|
+
|
|
102
|
+
MCP servers are spawned at client startup. Instruct the user to restart their
|
|
103
|
+
agent session or IDE to activate the newly connected BioMCP tools:
|
|
104
|
+
|
|
105
|
+
- **OpenCode**: Restart the session or open a new terminal session.
|
|
106
|
+
- **Claude Code**: Start a new session (`claude`).
|
|
107
|
+
- **Cursor / VS Code**: Reload the window or restart the application.
|
|
108
|
+
- **ZCode**: Reload the workspace or start a new ADE session.
|
|
109
|
+
- **Pi Coding Agent**: Start a new agent session (`pi`).
|
|
110
|
+
- **CodeBuddy**: Reload the window or restart the CLI session.
|
|
111
|
+
- **WorkBuddy**: Restart the application or switch workspace.
|
|
112
|
+
|
|
113
|
+
After restarting, verify connectivity by asking the agent to search for a gene
|
|
114
|
+
or article (e.g., `gene_search(query="BRAF")`).
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Stage 0 Zero-Dependency PowerShell Bootstrap for bioresearcher-onboard (Windows)
|
|
2
|
+
# Checks for existing Node >= 22.13; if missing, downloads pinned portable
|
|
3
|
+
# Node.js LTS into .bioresearcher-runtime\node, verifies SHA256, and hands off
|
|
4
|
+
# execution to onboard.mjs.
|
|
5
|
+
$ErrorActionPreference = "Stop"
|
|
6
|
+
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
|
|
7
|
+
$RuntimeRoot = if ($env:BIORESEARCHER_RUNTIME_DIR) { $env:BIORESEARCHER_RUNTIME_DIR } else { Join-Path (Get-Location).Path ".bioresearcher-runtime" }
|
|
8
|
+
$NodeDir = Join-Path $RuntimeRoot "node"
|
|
9
|
+
$NodeExe = Join-Path $NodeDir "node.exe"
|
|
10
|
+
|
|
11
|
+
$NodeVer = "v22.14.0"
|
|
12
|
+
|
|
13
|
+
# 1. Probe if host already satisfies Node >= 22.13
|
|
14
|
+
if (Get-Command node -ErrorAction SilentlyContinue) {
|
|
15
|
+
try {
|
|
16
|
+
$check = node -e "var v=process.versions.node.split('.');process.exit((v[0]>22||(v[0]==22&&v[1]>=13))?0:1)"
|
|
17
|
+
if ($LASTEXITCODE -eq 0) {
|
|
18
|
+
Write-Host "[bioresearcher-onboard] Found host $(node -v) on PATH"
|
|
19
|
+
& node "$ScriptDir\onboard.mjs" @args
|
|
20
|
+
exit $LASTEXITCODE
|
|
21
|
+
}
|
|
22
|
+
} catch {}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
# If already vendored in working directory, reuse directly
|
|
26
|
+
if (Test-Path $NodeExe) {
|
|
27
|
+
$env:PATH = "$NodeDir;$env:PATH"
|
|
28
|
+
& "$NodeExe" "$ScriptDir\onboard.mjs" @args
|
|
29
|
+
exit $LASTEXITCODE
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
Write-Host "[bioresearcher-onboard] Host Node >= 22.13 not found. Bootstrapping portable Node.js $NodeVer into .bioresearcher-runtime\..."
|
|
33
|
+
|
|
34
|
+
# 2. Architecture Detection
|
|
35
|
+
$Arch = if ([System.Runtime.InteropServices.RuntimeInformation]::OSArchitecture -eq [System.Runtime.InteropServices.Architecture]::Arm64) {
|
|
36
|
+
"arm64"
|
|
37
|
+
} else {
|
|
38
|
+
"x64"
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
# 3. Mirror Selection Probe (2-second integer timeout)
|
|
42
|
+
$MirrorBase = "https://nodejs.org/dist/$NodeVer"
|
|
43
|
+
$NpmRegistry = "https://registry.npmjs.org"
|
|
44
|
+
try {
|
|
45
|
+
$req = [System.Net.WebRequest]::Create("https://nodejs.org/dist/")
|
|
46
|
+
$req.Timeout = 2000
|
|
47
|
+
$res = $req.GetResponse()
|
|
48
|
+
$res.Close()
|
|
49
|
+
} catch {
|
|
50
|
+
Write-Host "[bioresearcher-onboard] nodejs.org unreachable; using npmmirror.com fast mirror"
|
|
51
|
+
$MirrorBase = "https://npmmirror.com/mirrors/node/$NodeVer"
|
|
52
|
+
$NpmRegistry = "https://registry.npmmirror.com"
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
$File = "node-$NodeVer-win-$Arch.zip"
|
|
56
|
+
$DownloadUrl = "$MirrorBase/$File"
|
|
57
|
+
|
|
58
|
+
$Checksums = @{
|
|
59
|
+
"x64" = "55b639295920b219bb2acbcfa00f90393a2789095b7323f79475c9f34795f217"
|
|
60
|
+
"arm64" = "2d71f5f9b2fffa33baa108c07d74b0d24e0c3dd8f441d567772ae0e3dd4b1a22"
|
|
61
|
+
}
|
|
62
|
+
$ExpectedSha = $Checksums[$Arch]
|
|
63
|
+
|
|
64
|
+
New-Item -ItemType Directory -Force -Path $RuntimeRoot | Out-Null
|
|
65
|
+
$TmpArchive = Join-Path $RuntimeRoot "node.zip"
|
|
66
|
+
|
|
67
|
+
Write-Host "[bioresearcher-onboard] Downloading $File..."
|
|
68
|
+
Invoke-WebRequest -Uri $DownloadUrl -OutFile $TmpArchive -UseBasicParsing
|
|
69
|
+
|
|
70
|
+
# 4. Checksum verification
|
|
71
|
+
$ActualSha = (Get-FileHash -Path $TmpArchive -Algorithm SHA256).Hash.ToLower()
|
|
72
|
+
if ($ActualSha -ne $ExpectedSha) {
|
|
73
|
+
Remove-Item -Force $TmpArchive -ErrorAction SilentlyContinue
|
|
74
|
+
Write-Error "SHA256 checksum verification failed for $File.`nExpected: $ExpectedSha`nActual: $ActualSha"
|
|
75
|
+
exit 1
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
# 5. Extract and flatten layout
|
|
79
|
+
$TmpExtract = Join-Path $RuntimeRoot "node-extract-tmp"
|
|
80
|
+
if (Test-Path $TmpExtract) { Remove-Item -Recurse -Force $TmpExtract }
|
|
81
|
+
New-Item -ItemType Directory -Force -Path $TmpExtract | Out-Null
|
|
82
|
+
Expand-Archive -Path $TmpArchive -DestinationPath $TmpExtract -Force
|
|
83
|
+
Remove-Item -Force $TmpArchive
|
|
84
|
+
|
|
85
|
+
New-Item -ItemType Directory -Force -Path $NodeDir | Out-Null
|
|
86
|
+
$ExtractedFolder = Get-ChildItem -Path $TmpExtract | Select-Object -First 1
|
|
87
|
+
Get-ChildItem -Path $ExtractedFolder.FullName | Move-Item -Destination $NodeDir -Force
|
|
88
|
+
Remove-Item -Recurse -Force $TmpExtract
|
|
89
|
+
|
|
90
|
+
Write-Host "[bioresearcher-onboard] Portable Node.js ready: $(& $NodeExe -v)"
|
|
91
|
+
|
|
92
|
+
# 6. Hand off to Stage 1
|
|
93
|
+
$env:PATH = "$NodeDir;$env:PATH"
|
|
94
|
+
$env:NPM_CONFIG_REGISTRY = $NpmRegistry
|
|
95
|
+
& "$NodeExe" "$ScriptDir\onboard.mjs" @args
|
|
96
|
+
exit $LASTEXITCODE
|