@cyanheads/brapi-mcp-server 0.6.3 → 0.7.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/CLAUDE.md +11 -4
- package/README.md +7 -3
- package/changelog/0.6.x/0.6.4.md +14 -0
- package/changelog/0.7.x/0.7.0.md +23 -0
- package/changelog/template.md +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp-server/resources/definitions/brapi-variable.resource.d.ts +30 -0
- package/dist/mcp-server/resources/definitions/brapi-variable.resource.d.ts.map +1 -0
- package/dist/mcp-server/resources/definitions/brapi-variable.resource.js +78 -0
- package/dist/mcp-server/resources/definitions/brapi-variable.resource.js.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-build-phenotype-matrix.tool.d.ts +81 -0
- package/dist/mcp-server/tools/definitions/brapi-build-phenotype-matrix.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-build-phenotype-matrix.tool.js +366 -0
- package/dist/mcp-server/tools/definitions/brapi-build-phenotype-matrix.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-connect.tool.d.ts +1 -1
- package/dist/mcp-server/tools/definitions/brapi-connect.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-dataframe-describe.tool.d.ts +1 -1
- package/dist/mcp-server/tools/definitions/brapi-dataframe-describe.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-dataframe-drop.tool.d.ts +1 -1
- package/dist/mcp-server/tools/definitions/brapi-dataframe-drop.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-dataframe-export.tool.d.ts +1 -1
- package/dist/mcp-server/tools/definitions/brapi-dataframe-export.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-dataframe-query.tool.d.ts +1 -1
- package/dist/mcp-server/tools/definitions/brapi-dataframe-query.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-describe-filters.tool.d.ts +1 -1
- package/dist/mcp-server/tools/definitions/brapi-describe-filters.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-export-genotype-matrix.tool.d.ts +88 -0
- package/dist/mcp-server/tools/definitions/brapi-export-genotype-matrix.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-export-genotype-matrix.tool.js +494 -0
- package/dist/mcp-server/tools/definitions/brapi-export-genotype-matrix.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.d.ts +7 -5
- package/dist/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.js +67 -120
- package/dist/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-germplasm.tool.d.ts +8 -6
- package/dist/mcp-server/tools/definitions/brapi-find-germplasm.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-germplasm.tool.js +54 -33
- package/dist/mcp-server/tools/definitions/brapi-find-germplasm.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-images.tool.d.ts +8 -6
- package/dist/mcp-server/tools/definitions/brapi-find-images.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-images.tool.js +54 -33
- package/dist/mcp-server/tools/definitions/brapi-find-images.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-locations.tool.d.ts +8 -6
- package/dist/mcp-server/tools/definitions/brapi-find-locations.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-locations.tool.js +62 -41
- package/dist/mcp-server/tools/definitions/brapi-find-locations.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-observations.tool.d.ts +8 -6
- package/dist/mcp-server/tools/definitions/brapi-find-observations.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-observations.tool.js +54 -33
- package/dist/mcp-server/tools/definitions/brapi-find-observations.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-studies.tool.d.ts +8 -6
- package/dist/mcp-server/tools/definitions/brapi-find-studies.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-studies.tool.js +52 -33
- package/dist/mcp-server/tools/definitions/brapi-find-studies.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-variables.tool.d.ts +8 -6
- package/dist/mcp-server/tools/definitions/brapi-find-variables.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-variables.tool.js +54 -33
- package/dist/mcp-server/tools/definitions/brapi-find-variables.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-variants.tool.d.ts +8 -6
- package/dist/mcp-server/tools/definitions/brapi-find-variants.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-variants.tool.js +54 -33
- package/dist/mcp-server/tools/definitions/brapi-find-variants.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-germplasm-performance.tool.d.ts +60 -0
- package/dist/mcp-server/tools/definitions/brapi-germplasm-performance.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-germplasm-performance.tool.js +416 -0
- package/dist/mcp-server/tools/definitions/brapi-germplasm-performance.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-get-germplasm.tool.d.ts +1 -1
- package/dist/mcp-server/tools/definitions/brapi-get-germplasm.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-get-image.tool.d.ts +1 -1
- package/dist/mcp-server/tools/definitions/brapi-get-image.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-get-study.tool.d.ts +1 -1
- package/dist/mcp-server/tools/definitions/brapi-get-study.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-raw-get.tool.d.ts +1 -1
- package/dist/mcp-server/tools/definitions/brapi-raw-get.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-raw-search.tool.d.ts +1 -1
- package/dist/mcp-server/tools/definitions/brapi-raw-search.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-server-info.tool.d.ts +1 -1
- package/dist/mcp-server/tools/definitions/brapi-server-info.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-submit-observations.tool.d.ts +1 -1
- package/dist/mcp-server/tools/definitions/brapi-submit-observations.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-walk-pedigree.tool.d.ts +1 -1
- package/dist/mcp-server/tools/definitions/brapi-walk-pedigree.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/index.d.ts +225 -61
- package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/index.js +6 -0
- package/dist/mcp-server/tools/definitions/index.js.map +1 -1
- package/dist/mcp-server/tools/shared/canvas-columns.d.ts +32 -0
- package/dist/mcp-server/tools/shared/canvas-columns.d.ts.map +1 -0
- package/dist/mcp-server/tools/shared/canvas-columns.js +98 -0
- package/dist/mcp-server/tools/shared/canvas-columns.js.map +1 -0
- package/dist/mcp-server/tools/shared/find-helpers.d.ts +1 -1
- package/dist/mcp-server/tools/shared/find-helpers.d.ts.map +1 -1
- package/dist/mcp-server/tools/shared/find-helpers.js +6 -2
- package/dist/mcp-server/tools/shared/find-helpers.js.map +1 -1
- package/dist/mcp-server/tools/shared/genotype-calls.d.ts +81 -0
- package/dist/mcp-server/tools/shared/genotype-calls.d.ts.map +1 -0
- package/dist/mcp-server/tools/shared/genotype-calls.js +172 -0
- package/dist/mcp-server/tools/shared/genotype-calls.js.map +1 -0
- package/dist/mcp-server/tools/shared/observations.d.ts +87 -0
- package/dist/mcp-server/tools/shared/observations.d.ts.map +1 -0
- package/dist/mcp-server/tools/shared/observations.js +285 -0
- package/dist/mcp-server/tools/shared/observations.js.map +1 -0
- package/manifest.json +1 -1
- package/package.json +6 -5
- package/server.json +3 -3
package/CLAUDE.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Agent Protocol
|
|
2
2
|
|
|
3
3
|
**Server:** brapi-mcp-server
|
|
4
|
-
**Version:** 0.
|
|
4
|
+
**Version:** 0.7.0
|
|
5
5
|
**Framework:** [@cyanheads/mcp-ts-core](https://www.npmjs.com/package/@cyanheads/mcp-ts-core)
|
|
6
6
|
|
|
7
7
|
> **Read the framework docs first:** `node_modules/@cyanheads/mcp-ts-core/CLAUDE.md` contains the full API reference — builders, Context, error codes, exports, patterns. This file covers server-specific conventions only.
|
|
@@ -168,7 +168,7 @@ Handlers receive a unified `ctx` object. Currently used surface:
|
|
|
168
168
|
| `ctx.requestId` | Unique request ID — auto-attached to every `ctx.log` entry. |
|
|
169
169
|
| `ctx.tenantId` | Tenant ID from JWT or `'default'` for stdio / HTTP+`auth=none` — outer scope on all `ctx.state` reads/writes. |
|
|
170
170
|
|
|
171
|
-
`ctx.elicit` is used by `brapi_submit_observations` to gate apply-mode writes behind user confirmation (with explicit `force: true` as the bypass). `ctx.sample` and `ctx.progress` are not used yet — they'll show up when long-running workflows (pedigree traversal, genotype-call pulls) need progress reporting or LLM sampling. `ctx.fail(reason, …)` is the typed thrower keyed off declared `errors[]` contracts — used by
|
|
171
|
+
`ctx.elicit` is used by `brapi_submit_observations` to gate apply-mode writes behind user confirmation (with explicit `force: true` as the bypass). `ctx.sample` and `ctx.progress` are not used yet — they'll show up when long-running workflows (pedigree traversal, genotype-call pulls) need progress reporting or LLM sampling. `ctx.fail(reason, …)` is the typed thrower keyed off declared `errors[]` contracts — used by 14 tools and 1 resource today. `ctx.recoveryFor(reason)` resolves the matching contract entry's recovery hint into `data.recovery.hint` so it surfaces on the wire.
|
|
172
172
|
|
|
173
173
|
---
|
|
174
174
|
|
|
@@ -176,7 +176,7 @@ Handlers receive a unified `ctx` object. Currently used surface:
|
|
|
176
176
|
|
|
177
177
|
Handlers throw — the framework catches, classifies, and formats.
|
|
178
178
|
|
|
179
|
-
**Default for new tools: typed error contract.** Declare `errors: [{ reason, code, when, recovery, retryable? }]` on `tool()` to receive a typed `ctx.fail(reason, …)` keyed by the declared reason union. TypeScript catches `ctx.fail('typo')` at compile time, `data.reason` is auto-populated for observability, and the linter enforces conformance against the handler body. The `recovery` field is required descriptive metadata (≥ 5 words, lint-validated); to surface it on the wire, spread `...ctx.recoveryFor('reason')` into `data` or pass an explicit `{ recovery: { hint: '...' } }` when runtime context matters. Baseline codes (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`) bubble freely and don't need declaring. Live across the BrAPI surface today: `
|
|
179
|
+
**Default for new tools: typed error contract.** Declare `errors: [{ reason, code, when, recovery, retryable? }]` on `tool()` to receive a typed `ctx.fail(reason, …)` keyed by the declared reason union. TypeScript catches `ctx.fail('typo')` at compile time, `data.reason` is auto-populated for observability, and the linter enforces conformance against the handler body. The `recovery` field is required descriptive metadata (≥ 5 words, lint-validated); to surface it on the wire, spread `...ctx.recoveryFor('reason')` into `data` or pass an explicit `{ recovery: { hint: '...' } }` when runtime context matters. Baseline codes (`InternalError`, `ServiceUnavailable`, `Timeout`, `ValidationError`, `SerializationError`) bubble freely and don't need declaring. Live across the BrAPI surface today: `brapi_build_phenotype_matrix`, `brapi_dataframe_describe`, `brapi_dataframe_export`, `brapi_dataframe_query`, `brapi_describe_filters`, `brapi_export_genotype_matrix`, `brapi_find_genotype_calls`, `brapi_germplasm_performance`, `brapi_get_germplasm`, `brapi_get_image`, `brapi_get_study`, `brapi_raw_get`, `brapi_raw_search`, `brapi_submit_observations`, plus the `brapi://variable/{observationVariableDbId}` resource.
|
|
180
180
|
|
|
181
181
|
```ts
|
|
182
182
|
errors: [
|
|
@@ -219,7 +219,7 @@ Available factories include `notFound`, `validationError`, `forbidden`, `unautho
|
|
|
219
219
|
|
|
220
220
|
```text
|
|
221
221
|
src/
|
|
222
|
-
index.ts # createApp() entry point — registers
|
|
222
|
+
index.ts # createApp() entry point — registers 25 tools, 6 resources, 2 prompts; inits 7 services
|
|
223
223
|
config/
|
|
224
224
|
server-config.ts # BRAPI_* env vars (Zod schema, lazy-parsed)
|
|
225
225
|
alias-credentials.ts # Per-alias env-var resolution (BRAPI_<ALIAS>_*) for brapi_connect
|
|
@@ -254,6 +254,9 @@ src/
|
|
|
254
254
|
brapi-dataframe-query.tool.ts # Run SQL across canvas dataframes (SELECT only); typed columns response
|
|
255
255
|
brapi-dataframe-drop.tool.ts # Drop a dataframe by name (opt-in via BRAPI_CANVAS_DROP_ENABLED)
|
|
256
256
|
brapi-dataframe-export.tool.ts # Write CSV/Parquet/JSON to BRAPI_EXPORT_DIR (opt-in, stdio-only)
|
|
257
|
+
brapi-build-phenotype-matrix.tool.ts # Germplasm × trait matrix from studies; materialized as canvas dataframe
|
|
258
|
+
brapi-germplasm-performance.tool.ts # Per-variable aggregates (n, mean, median, sd) for a single germplasm
|
|
259
|
+
brapi-export-genotype-matrix.tool.ts # Genotype calls → germplasm × variant dataframe + VCF-lite / PLINK serialization
|
|
257
260
|
brapi-submit-observations.tool.ts # Two-phase observation write — preview / apply (POST + PUT) with elicit gate
|
|
258
261
|
brapi-raw-get.tool.ts # Last-resort GET passthrough with routing nudge
|
|
259
262
|
brapi-raw-search.tool.ts # Last-resort POST /search passthrough with async polling
|
|
@@ -262,6 +265,9 @@ src/
|
|
|
262
265
|
orientation-envelope.ts # Shared envelope builder + formatter
|
|
263
266
|
find-helpers.ts # Alias / loadLimit / extraFilters fragments, mergeFilters, maybeSpill, DataframeHandleSchema
|
|
264
267
|
raw-routing-hints.ts # Routing nudges emitted by raw_get / raw_search when a curated tool exists
|
|
268
|
+
canvas-columns.ts # SQL-safe column-name sanitizer + variableLegend builder (shared by matrix tools)
|
|
269
|
+
observations.ts # Study-anchored observation pull shared by phenotype-matrix and germplasm-performance
|
|
270
|
+
genotype-calls.ts # Async genotype-call collector shared by find-genotype-calls and export-genotype-matrix
|
|
265
271
|
resources/
|
|
266
272
|
definitions/
|
|
267
273
|
brapi-server-info.resource.ts # brapi://server/info — orientation envelope (default connection)
|
|
@@ -269,6 +275,7 @@ src/
|
|
|
269
275
|
brapi-study.resource.ts # brapi://study/{studyDbId} — single study with FKs
|
|
270
276
|
brapi-germplasm.resource.ts # brapi://germplasm/{germplasmDbId} — single germplasm with attributes + parents
|
|
271
277
|
brapi-filters.resource.ts # brapi://filters/{endpoint} — filter catalog
|
|
278
|
+
brapi-variable.resource.ts # brapi://variable/{observationVariableDbId} — observation variable (trait, scale, method)
|
|
272
279
|
prompts/
|
|
273
280
|
definitions/
|
|
274
281
|
brapi-eda-study.prompt.ts # EDA playbook for one study (orient → variables → coverage → outliers → report)
|
package/README.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
<div align="center">
|
|
2
2
|
<h1>@cyanheads/brapi-mcp-server</h1>
|
|
3
3
|
<p><b>A collaborative BrAPI v2.1 workspace for multi-agent research via MCP. Search studies, germplasm, genotypes, & more - across Breedbase, T3, Sweetpotatobase, & any BrAPI v2-compliant server.</b>
|
|
4
|
-
<div>
|
|
4
|
+
<div>25 Tools • 6 Resources • 2 Prompts • Multi-agent collaboration</div>
|
|
5
5
|
</p>
|
|
6
6
|
</div>
|
|
7
7
|
|
|
8
8
|
<div align="center">
|
|
9
9
|
|
|
10
|
-
[](https://www.npmjs.com/package/@cyanheads/brapi-mcp-server) [](https://www.npmjs.com/package/@cyanheads/brapi-mcp-server) [](./CHANGELOG.md) [](https://modelcontextprotocol.io/) [](./LICENSE) [](https://www.typescriptlang.org/) [](https://bun.sh/) [](./CHANGELOG.md)
|
|
11
11
|
|
|
12
12
|
</div>
|
|
13
13
|
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
## Tools
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
25 tools grouped by shape — connection tools bootstrap a session, `find_*` tools return a summarized page plus distributions and spill overflow rows into a canvas dataframe that agents on the same session can query or hand off by ID, `get_*` tools fetch a single record with companion counts, plus pedigree walking, an embedded SQL workspace over spilled rows (DuckDB-backed), file export for human handoff, an additive write surface for observations, and raw passthrough escape hatches.
|
|
27
27
|
|
|
28
28
|
### Orient
|
|
29
29
|
|
|
@@ -58,6 +58,9 @@
|
|
|
58
58
|
| `brapi_dataframe_query` | SELECT SQL across in-memory dataframes (DuckDB-backed). Spilled `find_*` rows auto-register as `df_<uuid>`. Read-only — multi-statement, non-SELECT, file-reads, and exports rejected. Returns typed columns (`{ name, type }[]`). |
|
|
59
59
|
| `brapi_dataframe_drop` | _Opt-in via `BRAPI_CANVAS_DROP_ENABLED=true`._ Drop a dataframe by name. Idempotent. Dataframes also expire via TTL when left unmanaged. |
|
|
60
60
|
| `brapi_dataframe_export` | _Opt-in via `BRAPI_EXPORT_DIR=<path>`, stdio-only._ Export a dataframe to disk (CSV / Parquet / JSON) under the configured directory and return the absolute path for the human to open. Optional `columns` projection or `sql` filter materializes a derived table for the export, dropped after. |
|
|
61
|
+
| `brapi_build_phenotype_matrix` | Build a germplasm × trait matrix from one or more studies and materialize it as a canvas dataframe. Supports wide (pivot) or long shape with configurable per-cell aggregation. |
|
|
62
|
+
| `brapi_germplasm_performance` | Per-variable performance aggregates (n, mean, median, sd, min, max, studyCount) for a single germplasm across all studies where it has observations. |
|
|
63
|
+
| `brapi_export_genotype_matrix` | Export genotype calls for a variant set as a germplasm × variant canvas dataframe; also serializes to VCF-lite or PLINK `.ped`/`.map` text. |
|
|
61
64
|
|
|
62
65
|
### Write (opt-in: `BRAPI_ENABLE_WRITES=true`)
|
|
63
66
|
|
|
@@ -87,6 +90,7 @@ URI-addressable mirrors of the curated tool surface for clients that prefer reso
|
|
|
87
90
|
| `brapi://study/{studyDbId}` | `brapi_get_study` |
|
|
88
91
|
| `brapi://germplasm/{germplasmDbId}` | `brapi_get_germplasm` |
|
|
89
92
|
| `brapi://filters/{endpoint}` | `brapi_describe_filters` |
|
|
93
|
+
| `brapi://variable/{observationVariableDbId}` | Observation variable record (trait, scale, method, ontology) |
|
|
90
94
|
|
|
91
95
|
---
|
|
92
96
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Enrichment adoption — brapi_find_* tools now surface filter echoes, result totals, and empty-result guidance via ctx.enrich(); @cyanheads/mcp-ts-core ^0.9.13 → ^0.9.16"
|
|
3
|
+
breaking: false
|
|
4
|
+
security: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.6.4 — 2026-05-30
|
|
8
|
+
|
|
9
|
+
## Changed
|
|
10
|
+
|
|
11
|
+
- **`brapi_find_studies`, `brapi_find_germplasm`, `brapi_find_observations`, `brapi_find_variables`, `brapi_find_images`, `brapi_find_locations`, `brapi_find_variants`, `brapi_find_genotype_calls`** — `returnedCount`, `totalCount`, `appliedFilters`, `refinementHint`, and `warnings` moved from the `output` schema into a typed `enrichment` block via `ctx.enrich()`. Both `structuredContent` (JSON) and the `content[]` markdown trailer receive the enrichment; the domain return type no longer carries these fields. An `enrich.notice()` fires when a tool returns zero rows, surfacing filter-broadening guidance.
|
|
12
|
+
- **`renderFindHeader()`** — `totalCount` is now optional; omitted when the server does not report a total (renders `N <noun>` instead of `N of M <noun>`).
|
|
13
|
+
- **`@cyanheads/mcp-ts-core`** ^0.9.13 → ^0.9.16.
|
|
14
|
+
- **`format:unsafe` script** separated from `format` (`biome check --write` vs `biome check --write --unsafe`).
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "phenotype matrix, germplasm performance, genotype export, observation variable resource"
|
|
3
|
+
breaking: false
|
|
4
|
+
security: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# 0.7.0 — 2026-06-01
|
|
8
|
+
|
|
9
|
+
## Added
|
|
10
|
+
|
|
11
|
+
- **`brapi_build_phenotype_matrix`** — builds a germplasm × trait observation matrix from one or more studies and materializes it as a canvas dataframe. Supports wide (pivot) and long shape with configurable per-cell aggregation; wide-column names are SQL-safe identifiers with a `variableLegend` map back to display names. Study-anchored pull prefers `GET /observations?studyDbId`, falls back to observation-unit embedded observations then germplasm-anchored observations for servers where the `studyDbId` filter is unsupported. Shared observation-pull machinery with `brapi_germplasm_performance`. ([#8](https://github.com/cyanheads/brapi-mcp-server/issues/8))
|
|
12
|
+
- **`brapi_germplasm_performance`** — per-variable performance aggregates (n, mean, median, sample sd, min, max, studyCount, studyDbIds, seasons) for a single germplasm across all studies where it has observations. Discovers candidate studies via `GET /studies?germplasmDbIds` with a dialect-honor cross-check that warns when a server silently ignores the filter. ([#9](https://github.com/cyanheads/brapi-mcp-server/issues/9))
|
|
13
|
+
- **`brapi_export_genotype_matrix`** — exports genotype calls for a variant set as a germplasm × variant canvas dataframe (SQL-safe column names, `variantColumnLegend` map); also serializes to VCF-lite (`#CHROM POS ID REF ALT` + per-sample genotype columns) and PLINK (`.ped` + `.map`). Reuses `tools/shared/genotype-calls.ts` extracted from `brapi_find_genotype_calls`. ([#12](https://github.com/cyanheads/brapi-mcp-server/issues/12))
|
|
14
|
+
- **`brapi://variable/{observationVariableDbId}`** resource — single observation-variable record (trait, scale, method, ontology) on the default connection via `GET /variables/{id}`. ([#14](https://github.com/cyanheads/brapi-mcp-server/issues/14))
|
|
15
|
+
- **`tools/shared/canvas-columns.ts`** — SQL-safe column-name sanitizer and `variableLegend` / `variantColumnLegend` builder, shared by `brapi_build_phenotype_matrix` and `brapi_export_genotype_matrix`.
|
|
16
|
+
- **`tools/shared/observations.ts`** — study-anchored observation pull shared by `brapi_build_phenotype_matrix` and `brapi_germplasm_performance`.
|
|
17
|
+
- **`tools/shared/genotype-calls.ts`** — async genotype-call collector extracted from `brapi_find_genotype_calls`, shared by `brapi_export_genotype_matrix`.
|
|
18
|
+
|
|
19
|
+
## Changed
|
|
20
|
+
|
|
21
|
+
- **`brapi_find_genotype_calls`** refactored to consume `tools/shared/genotype-calls.ts`; behavior unchanged.
|
|
22
|
+
- **`@duckdb/node-api`** `^1.5.3-r.2` → `^1.5.3-r.3`
|
|
23
|
+
- **`vitest`** `^4.1.7` → `^4.1.8` (dev)
|
package/changelog/template.md
CHANGED
|
@@ -43,7 +43,7 @@ security: false
|
|
|
43
43
|
name the symbol, state what changed, stop. Use a second sentence only when
|
|
44
44
|
it carries weight. If a bullet feels long, it is.
|
|
45
45
|
|
|
46
|
-
Cut: mechanism walkthroughs (those belong in JSDoc, AGENTS.md, or the
|
|
46
|
+
Cut: mechanism walkthroughs (those belong in JSDoc, CLAUDE.md/AGENTS.md, or the
|
|
47
47
|
relevant skill), ceremonial framings ("This release introduces…",
|
|
48
48
|
backwards-compat paragraphs), file-by-file test enumerations, internal
|
|
49
49
|
implementation notes. Prefer code/symbol names over English re-explanations.
|
package/dist/index.js
CHANGED
|
@@ -46,6 +46,7 @@ import { brapiFiltersResource } from './mcp-server/resources/definitions/brapi-f
|
|
|
46
46
|
import { brapiGermplasmResource } from './mcp-server/resources/definitions/brapi-germplasm.resource.js';
|
|
47
47
|
import { brapiServerInfoResource } from './mcp-server/resources/definitions/brapi-server-info.resource.js';
|
|
48
48
|
import { brapiStudyResource } from './mcp-server/resources/definitions/brapi-study.resource.js';
|
|
49
|
+
import { brapiVariableResource } from './mcp-server/resources/definitions/brapi-variable.resource.js';
|
|
49
50
|
import { dropToolDefinitions, exportToolDefinitions, readOnlyToolDefinitions, writeToolDefinitions, } from './mcp-server/tools/definitions/index.js';
|
|
50
51
|
const serverConfig = getServerConfig();
|
|
51
52
|
/**
|
|
@@ -100,6 +101,7 @@ await createApp({
|
|
|
100
101
|
brapiCallsResource,
|
|
101
102
|
brapiStudyResource,
|
|
102
103
|
brapiGermplasmResource,
|
|
104
|
+
brapiVariableResource,
|
|
103
105
|
brapiFiltersResource,
|
|
104
106
|
],
|
|
105
107
|
prompts: [brapiEdaStudy, brapiMetaAnalysis],
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview `brapi://variable/{observationVariableDbId}` — single
|
|
3
|
+
* observation-variable record on the default connection. The single-record,
|
|
4
|
+
* URI-addressable counterpart to `brapi_find_variables` (which returns a list
|
|
5
|
+
* envelope). Fills the resource gap alongside `brapi://study/{id}` and
|
|
6
|
+
* `brapi://germplasm/{id}`.
|
|
7
|
+
*
|
|
8
|
+
* Fetches the canonical `/variables/{observationVariableDbId}` payload directly
|
|
9
|
+
* (trait, scale, method, ontology) and returns it verbatim — mirroring how
|
|
10
|
+
* `brapi_get_germplasm` reads `/germplasm/{id}`. A 404 (or an empty record)
|
|
11
|
+
* surfaces as the typed `variable_not_found` error.
|
|
12
|
+
*
|
|
13
|
+
* @module mcp-server/resources/definitions/brapi-variable.resource
|
|
14
|
+
*/
|
|
15
|
+
import { z } from '@cyanheads/mcp-ts-core';
|
|
16
|
+
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
17
|
+
export declare const brapiVariableResource: import("@cyanheads/mcp-ts-core").ResourceDefinition<z.ZodObject<{
|
|
18
|
+
observationVariableDbId: z.ZodString;
|
|
19
|
+
}, z.core.$strip>, undefined, readonly [{
|
|
20
|
+
readonly reason: "unknown_alias";
|
|
21
|
+
readonly code: JsonRpcErrorCode.NotFound;
|
|
22
|
+
readonly when: "No default BrAPI connection has been registered";
|
|
23
|
+
readonly recovery: "Call brapi_connect (without an alias, or with alias `default`) before reading this resource.";
|
|
24
|
+
}, {
|
|
25
|
+
readonly reason: "variable_not_found";
|
|
26
|
+
readonly code: JsonRpcErrorCode.NotFound;
|
|
27
|
+
readonly when: "Upstream returned no observation variable record for the requested DbId";
|
|
28
|
+
readonly recovery: "Verify the observationVariableDbId on the target server, or run brapi_find_variables to discover valid IDs.";
|
|
29
|
+
}]>;
|
|
30
|
+
//# sourceMappingURL=brapi-variable.resource.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brapi-variable.resource.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/brapi-variable.resource.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAY,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAQjE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;GA8EhC,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview `brapi://variable/{observationVariableDbId}` — single
|
|
3
|
+
* observation-variable record on the default connection. The single-record,
|
|
4
|
+
* URI-addressable counterpart to `brapi_find_variables` (which returns a list
|
|
5
|
+
* envelope). Fills the resource gap alongside `brapi://study/{id}` and
|
|
6
|
+
* `brapi://germplasm/{id}`.
|
|
7
|
+
*
|
|
8
|
+
* Fetches the canonical `/variables/{observationVariableDbId}` payload directly
|
|
9
|
+
* (trait, scale, method, ontology) and returns it verbatim — mirroring how
|
|
10
|
+
* `brapi_get_germplasm` reads `/germplasm/{id}`. A 404 (or an empty record)
|
|
11
|
+
* surfaces as the typed `variable_not_found` error.
|
|
12
|
+
*
|
|
13
|
+
* @module mcp-server/resources/definitions/brapi-variable.resource
|
|
14
|
+
*/
|
|
15
|
+
import { resource, z } from '@cyanheads/mcp-ts-core';
|
|
16
|
+
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
17
|
+
import { buildRequestOptions, isUpstreamNotFound, requireRegisteredConnection, } from '../../../mcp-server/tools/shared/find-helpers.js';
|
|
18
|
+
import { getBrapiClient } from '../../../services/brapi-client/index.js';
|
|
19
|
+
export const brapiVariableResource = resource('brapi://variable/{observationVariableDbId}', {
|
|
20
|
+
name: 'brapi-variable',
|
|
21
|
+
title: 'BrAPI observation variable record',
|
|
22
|
+
description: 'Single observation-variable resource on the default BrAPI connection — the canonical /variables/{id} record (trait, scale, method, ontology), addressable by URI. The single-record equivalent of brapi_find_variables.',
|
|
23
|
+
mimeType: 'application/json',
|
|
24
|
+
errors: [
|
|
25
|
+
{
|
|
26
|
+
reason: 'unknown_alias',
|
|
27
|
+
code: JsonRpcErrorCode.NotFound,
|
|
28
|
+
when: 'No default BrAPI connection has been registered',
|
|
29
|
+
recovery: 'Call brapi_connect (without an alias, or with alias `default`) before reading this resource.',
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
reason: 'variable_not_found',
|
|
33
|
+
code: JsonRpcErrorCode.NotFound,
|
|
34
|
+
when: 'Upstream returned no observation variable record for the requested DbId',
|
|
35
|
+
recovery: 'Verify the observationVariableDbId on the target server, or run brapi_find_variables to discover valid IDs.',
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
params: z.object({
|
|
39
|
+
observationVariableDbId: z
|
|
40
|
+
.string()
|
|
41
|
+
.min(1)
|
|
42
|
+
.describe('Observation variable identifier on the default connection.'),
|
|
43
|
+
}),
|
|
44
|
+
async handler(params, ctx) {
|
|
45
|
+
const client = getBrapiClient();
|
|
46
|
+
const connection = await requireRegisteredConnection(ctx, undefined);
|
|
47
|
+
const id = encodeURIComponent(params.observationVariableDbId);
|
|
48
|
+
let env;
|
|
49
|
+
try {
|
|
50
|
+
env = await client.get(connection.baseUrl, `/variables/${id}`, ctx, buildRequestOptions(connection, undefined, { singleton: true }));
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
if (isUpstreamNotFound(err)) {
|
|
54
|
+
throw ctx.fail('variable_not_found', `Observation variable '${params.observationVariableDbId}' not found on ${connection.baseUrl}.`, {
|
|
55
|
+
observationVariableDbId: params.observationVariableDbId,
|
|
56
|
+
baseUrl: connection.baseUrl,
|
|
57
|
+
...ctx.recoveryFor('variable_not_found'),
|
|
58
|
+
}, { cause: err });
|
|
59
|
+
}
|
|
60
|
+
throw err;
|
|
61
|
+
}
|
|
62
|
+
const variable = env.result;
|
|
63
|
+
if (!variable ||
|
|
64
|
+
typeof variable !== 'object' ||
|
|
65
|
+
!variable.observationVariableDbId) {
|
|
66
|
+
throw ctx.fail('variable_not_found', `Observation variable '${params.observationVariableDbId}' not found on ${connection.baseUrl}.`, {
|
|
67
|
+
observationVariableDbId: params.observationVariableDbId,
|
|
68
|
+
baseUrl: connection.baseUrl,
|
|
69
|
+
...ctx.recoveryFor('variable_not_found'),
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
return variable;
|
|
73
|
+
},
|
|
74
|
+
list: async () => ({
|
|
75
|
+
resources: [],
|
|
76
|
+
}),
|
|
77
|
+
});
|
|
78
|
+
//# sourceMappingURL=brapi-variable.resource.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brapi-variable.resource.js","sourceRoot":"","sources":["../../../../src/mcp-server/resources/definitions/brapi-variable.resource.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview `brapi_build_phenotype_matrix` — pull observations across one or
|
|
3
|
+
* more studies and pivot them into a germplasm × trait matrix materialized as a
|
|
4
|
+
* canvas dataframe. Returns a dataframe handle plus a summary of dimensions,
|
|
5
|
+
* aggregate method, and any warnings encountered during the pull.
|
|
6
|
+
*
|
|
7
|
+
* The per-study observation pull (with its `/observations` → `/observationunits`
|
|
8
|
+
* fallback chain) lives in `../shared/observations.ts`, shared with
|
|
9
|
+
* `brapi_germplasm_performance`.
|
|
10
|
+
*
|
|
11
|
+
* Column safety: wide-matrix column names are SQL-safe identifiers derived from
|
|
12
|
+
* `observationVariableDbId` via `../shared/canvas-columns.ts` — BrAPI DbIds are
|
|
13
|
+
* routinely numeric (Breedbase) or collide with reserved SQL words, both of
|
|
14
|
+
* which the canvas identifier gate rejects. A `variableLegend` mapping safe
|
|
15
|
+
* column → display name is returned so callers can resolve columns back.
|
|
16
|
+
*
|
|
17
|
+
* @module mcp-server/tools/definitions/brapi-build-phenotype-matrix.tool
|
|
18
|
+
*/
|
|
19
|
+
import { z } from '@cyanheads/mcp-ts-core';
|
|
20
|
+
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
21
|
+
export declare const brapiBuildPhenotypeMatrix: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
|
|
22
|
+
alias: z.ZodOptional<z.ZodString>;
|
|
23
|
+
studies: z.ZodArray<z.ZodString>;
|
|
24
|
+
variables: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
25
|
+
germplasm: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
26
|
+
shape: z.ZodDefault<z.ZodEnum<{
|
|
27
|
+
wide: "wide";
|
|
28
|
+
long: "long";
|
|
29
|
+
}>>;
|
|
30
|
+
aggregate: z.ZodDefault<z.ZodEnum<{
|
|
31
|
+
all: "all";
|
|
32
|
+
mean: "mean";
|
|
33
|
+
median: "median";
|
|
34
|
+
first: "first";
|
|
35
|
+
}>>;
|
|
36
|
+
loadLimit: z.ZodOptional<z.ZodNumber>;
|
|
37
|
+
extraFilters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
38
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
39
|
+
alias: z.ZodString;
|
|
40
|
+
studies: z.ZodArray<z.ZodString>;
|
|
41
|
+
shape: z.ZodEnum<{
|
|
42
|
+
wide: "wide";
|
|
43
|
+
long: "long";
|
|
44
|
+
}>;
|
|
45
|
+
aggregate: z.ZodEnum<{
|
|
46
|
+
all: "all";
|
|
47
|
+
mean: "mean";
|
|
48
|
+
median: "median";
|
|
49
|
+
first: "first";
|
|
50
|
+
}>;
|
|
51
|
+
observationCount: z.ZodNumber;
|
|
52
|
+
germplasmCount: z.ZodNumber;
|
|
53
|
+
variableCount: z.ZodNumber;
|
|
54
|
+
variableLegend: z.ZodRecord<z.ZodString, z.ZodString>;
|
|
55
|
+
dataframe: z.ZodOptional<z.ZodObject<{
|
|
56
|
+
tableName: z.ZodString;
|
|
57
|
+
rowCount: z.ZodNumber;
|
|
58
|
+
columns: z.ZodArray<z.ZodString>;
|
|
59
|
+
createdAt: z.ZodString;
|
|
60
|
+
expiresAt: z.ZodString;
|
|
61
|
+
truncated: z.ZodOptional<z.ZodBoolean>;
|
|
62
|
+
maxRows: z.ZodOptional<z.ZodNumber>;
|
|
63
|
+
}, z.core.$strip>>;
|
|
64
|
+
warnings: z.ZodArray<z.ZodString>;
|
|
65
|
+
}, z.core.$strip>, readonly [{
|
|
66
|
+
readonly reason: "unknown_alias";
|
|
67
|
+
readonly code: JsonRpcErrorCode.NotFound;
|
|
68
|
+
readonly when: "No connection has been registered under the requested alias";
|
|
69
|
+
readonly recovery: "Run brapi_connect with this alias (or omit `alias` to use the default connection) before calling brapi_build_phenotype_matrix.";
|
|
70
|
+
}, {
|
|
71
|
+
readonly reason: "all_filters_dropped";
|
|
72
|
+
readonly code: JsonRpcErrorCode.ValidationError;
|
|
73
|
+
readonly when: "The active dialect dropped every filter supplied — the call would silently widen to the unfiltered baseline";
|
|
74
|
+
readonly recovery: "Drop unsupported filters or use studies / germplasm / variables to scope the query to supported filter paths on the active dialect.";
|
|
75
|
+
}, {
|
|
76
|
+
readonly reason: "no_observation_path";
|
|
77
|
+
readonly code: JsonRpcErrorCode.ServiceUnavailable;
|
|
78
|
+
readonly when: "Neither /observations nor /observationunits returned data for any requested study after probing both paths";
|
|
79
|
+
readonly recovery: "Verify the studyDbIds exist and the BrAPI server exposes /observations or /observationunits. Use brapi_server_info to inspect the capability list.";
|
|
80
|
+
}], undefined>;
|
|
81
|
+
//# sourceMappingURL=brapi-build-phenotype-matrix.tool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brapi-build-phenotype-matrix.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/brapi-build-phenotype-matrix.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAoEjE,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAgPpC,CAAC"}
|