@cyanheads/brapi-mcp-server 0.4.10 → 0.4.12
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 +1 -1
- package/Dockerfile +9 -0
- package/README.md +24 -4
- package/changelog/0.4.x/0.4.11.md +19 -0
- package/changelog/0.4.x/0.4.12.md +29 -0
- package/dist/config/alias-credentials.d.ts +27 -15
- package/dist/config/alias-credentials.d.ts.map +1 -1
- package/dist/config/alias-credentials.js +71 -29
- package/dist/config/alias-credentials.js.map +1 -1
- package/dist/config/builtin-aliases.d.ts +51 -0
- package/dist/config/builtin-aliases.d.ts.map +1 -0
- package/dist/config/builtin-aliases.js +108 -0
- package/dist/config/builtin-aliases.js.map +1 -0
- package/dist/index.js +18 -6
- package/dist/index.js.map +1 -1
- package/dist/mcp-server/prompts/definitions/brapi-meta-analysis.prompt.js +4 -4
- package/dist/mcp-server/prompts/definitions/brapi-meta-analysis.prompt.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-connect.tool.d.ts +6 -0
- package/dist/mcp-server/tools/definitions/brapi-connect.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-connect.tool.js +3 -3
- package/dist/mcp-server/tools/definitions/brapi-connect.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-dataframe-describe.tool.d.ts +2 -2
- package/dist/mcp-server/tools/definitions/brapi-dataframe-describe.tool.js +2 -2
- package/dist/mcp-server/tools/definitions/brapi-dataframe-describe.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-dataframe-drop.tool.d.ts +2 -2
- package/dist/mcp-server/tools/definitions/brapi-dataframe-drop.tool.js +2 -2
- package/dist/mcp-server/tools/definitions/brapi-dataframe-drop.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-dataframe-query.tool.d.ts +2 -2
- package/dist/mcp-server/tools/definitions/brapi-dataframe-query.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-dataframe-query.tool.js +17 -20
- package/dist/mcp-server/tools/definitions/brapi-dataframe-query.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.d.ts +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.js +2 -2
- package/dist/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-locations.tool.js +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-locations.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-studies.tool.d.ts +1 -1
- 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 +8 -4
- package/dist/mcp-server/tools/definitions/brapi-find-studies.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-get-image.tool.js +1 -1
- package/dist/mcp-server/tools/definitions/brapi-get-image.tool.js.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-get-study.tool.js +8 -4
- package/dist/mcp-server/tools/definitions/brapi-get-study.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-manage-dataset.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-manage-dataset.tool.js +3 -3
- package/dist/mcp-server/tools/definitions/brapi-manage-dataset.tool.js.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.js +1 -1
- package/dist/mcp-server/tools/definitions/brapi-raw-search.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-server-info.tool.d.ts +6 -0
- 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.js +1 -1
- package/dist/mcp-server/tools/definitions/brapi-submit-observations.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/index.d.ts +22 -10
- package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -1
- package/dist/mcp-server/tools/shared/connect-auth-schema.d.ts.map +1 -1
- package/dist/mcp-server/tools/shared/connect-auth-schema.js +15 -6
- package/dist/mcp-server/tools/shared/connect-auth-schema.js.map +1 -1
- package/dist/mcp-server/tools/shared/find-helpers.js +1 -1
- package/dist/mcp-server/tools/shared/find-helpers.js.map +1 -1
- package/dist/mcp-server/tools/shared/orientation-envelope.d.ts +12 -0
- package/dist/mcp-server/tools/shared/orientation-envelope.d.ts.map +1 -1
- package/dist/mcp-server/tools/shared/orientation-envelope.js +45 -4
- package/dist/mcp-server/tools/shared/orientation-envelope.js.map +1 -1
- package/dist/mcp-server/tools/shared/raw-routing-hints.js +2 -2
- package/dist/mcp-server/tools/shared/raw-routing-hints.js.map +1 -1
- package/dist/services/canvas-bridge/canvas-bridge.d.ts.map +1 -1
- package/dist/services/canvas-bridge/canvas-bridge.js +10 -44
- package/dist/services/canvas-bridge/canvas-bridge.js.map +1 -1
- package/package.json +2 -2
- 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.
|
|
4
|
+
**Version:** 0.4.11
|
|
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.
|
package/Dockerfile
CHANGED
|
@@ -66,6 +66,15 @@ RUN if [ "$OTEL_ENABLED" = "true" ]; then \
|
|
|
66
66
|
@opentelemetry/semantic-conventions; \
|
|
67
67
|
fi
|
|
68
68
|
|
|
69
|
+
# Conditionally install the DuckDB optional peer dependency for the dataframe
|
|
70
|
+
# (canvas) surface. Default-on so the published image works out of the box with
|
|
71
|
+
# CANVAS_PROVIDER_TYPE=duckdb. Disable for size-sensitive self-builds with:
|
|
72
|
+
# docker build --build-arg CANVAS_ENABLED=false
|
|
73
|
+
ARG CANVAS_ENABLED=true
|
|
74
|
+
RUN if [ "$CANVAS_ENABLED" = "true" ]; then \
|
|
75
|
+
bun add @duckdb/node-api; \
|
|
76
|
+
fi
|
|
77
|
+
|
|
69
78
|
# Copy the compiled application code from the build stage
|
|
70
79
|
COPY --from=build /usr/src/app/dist ./dist
|
|
71
80
|
|
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
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://www.npmjs.com/package/@cyanheads/mcp-ts-core) [](https://modelcontextprotocol.io/)
|
|
11
11
|
|
|
12
12
|
[](./LICENSE) [](https://www.typescriptlang.org/) [](https://bun.sh/) [](./CHANGELOG.md)
|
|
13
13
|
|
|
@@ -77,7 +77,7 @@ Twenty-two tools grouped by shape — connection tools bootstrap a session, `fin
|
|
|
77
77
|
|
|
78
78
|
Session bootstrap. Authenticates to a BrAPI v2 server, registers the connection under a named alias, loads the capability profile via `CapabilityRegistry`, and inlines the full orientation envelope in the response. One call fully orients the agent.
|
|
79
79
|
|
|
80
|
-
- `baseUrl` and `auth` are optional — when omitted they fall back to `BRAPI_<ALIAS>_*`, then `BRAPI_DEFAULT_*`
|
|
80
|
+
- `baseUrl` and `auth` are optional — when omitted they fall back to `BRAPI_<ALIAS>_*`, then a built-in registry of public BrAPI servers (`cassava`, `sweetpotato`, `wheat`, `breedbase`), then `BRAPI_DEFAULT_*` (see [Per-alias credentials](#per-alias-credentials) and [Built-in aliases](#built-in-aliases)). Agents can call `brapi_connect({ alias: 'cassava' })` with nothing else and credentials never enter the LLM context
|
|
81
81
|
- Tagged-union auth input: `none`, `sgn` (session-token exchange), `oauth2` (client-credentials exchange), `bearer`, `api_key`
|
|
82
82
|
- Multiple concurrent connections per session via distinct aliases
|
|
83
83
|
- Forces a fresh capability load on every connect — the agent expects current state
|
|
@@ -511,11 +511,14 @@ See [`.env.example`](./.env.example) for the full list of optional overrides.
|
|
|
511
511
|
|
|
512
512
|
### Per-alias credentials
|
|
513
513
|
|
|
514
|
-
`brapi_connect` resolves `baseUrl` and `auth` from env vars when the agent omits them, so credentials never enter the LLM context.
|
|
514
|
+
`brapi_connect` resolves `baseUrl` and `auth` from env vars when the agent omits them, so credentials never enter the LLM context. Four layers of precedence:
|
|
515
515
|
|
|
516
516
|
1. **Explicit agent input** — always wins.
|
|
517
517
|
2. **Per-alias env vars** — `BRAPI_<ALIAS>_*` where the alias name is uppercased and hyphens become underscores (`my-server` → `BRAPI_MY_SERVER_*`).
|
|
518
|
-
3. **
|
|
518
|
+
3. **Built-in known-server registry** — see [Built-in aliases](#built-in-aliases) below.
|
|
519
|
+
4. **Default env vars** — `BRAPI_DEFAULT_*`, only consulted when the alias differs from `default`.
|
|
520
|
+
|
|
521
|
+
When the baseUrl is satisfied by a builtin, `BRAPI_DEFAULT_*` credentials are **not** layered on top — those belong to the default server, not whatever upstream the builtin happens to point at. Per-alias credentials still apply, since those were explicitly set for this alias.
|
|
519
522
|
|
|
520
523
|
Each alias carries **one** credential family — auth mode is derived from which fields are set:
|
|
521
524
|
|
|
@@ -549,6 +552,23 @@ BRAPI_SECURE_OAUTH_TOKEN_URL=https://auth.example.com/oauth/token
|
|
|
549
552
|
|
|
550
553
|
Then the agent calls `brapi_connect({ alias: 'cassava' })` — no `baseUrl`, no `auth`, no secrets in the prompt.
|
|
551
554
|
|
|
555
|
+
### Built-in aliases
|
|
556
|
+
|
|
557
|
+
The server ships with a curated registry of public BrAPI v2 endpoints. Each alias resolves out-of-the-box without any env vars — call `brapi_connect({ alias: 'cassava' })` and the resolver fills in the URL. Each entry is published under [Creative Commons Attribution](https://creativecommons.org/licenses/by/4.0/); the orientation envelope surfaces license, citation, and homepage in its `attribution` block so agents can satisfy reuse terms automatically.
|
|
558
|
+
|
|
559
|
+
| Alias | Upstream | Hosted by | Crop | Notes |
|
|
560
|
+
|:------|:---------|:----------|:-----|:------|
|
|
561
|
+
| `cassava` | [cassavabase.org](https://cassavabase.org/) | Boyce Thompson Institute | Cassava | NextGen Cassava project |
|
|
562
|
+
| `sweetpotato` | [sweetpotatobase.org](https://sweetpotatobase.org/) | Boyce Thompson Institute | Sweet potato | |
|
|
563
|
+
| `wheat` | [wheat.triticeaetoolbox.org](https://wheat.triticeaetoolbox.org/) | Triticeae Toolbox (T3) | Wheat | |
|
|
564
|
+
| `breedbase` | [breedbase.org](https://breedbase.org/) | Boyce Thompson Institute | _Demo_ | Sample data only — not production records. Useful for onboarding and tests. |
|
|
565
|
+
|
|
566
|
+
**Override:** set `BRAPI_<ALIAS>_BASE_URL=...` to repoint an alias at a staging mirror or a fork — env always wins over the builtin URL. Set `BRAPI_<ALIAS>_USERNAME=...` etc. to attach credentials on top of the builtin URL when you need write access (each Breedbase instance has its own user table — separate registration on each upstream).
|
|
567
|
+
|
|
568
|
+
**Opt-out:** `BRAPI_BUILTIN_ALIASES_DISABLED=cassava,wheat` (comma-separated, case-insensitive) removes specific aliases from resolution and discovery for deployments that prefer a stripped surface.
|
|
569
|
+
|
|
570
|
+
**Citation:** all four shipped builtins reference the same foundational paper — Morales et al. 2022, _"Breedbase: a digital ecosystem for modern plant breeding."_ G3 12(7): jkac078. [doi:10.1093/g3journal/jkac078](https://doi.org/10.1093/g3journal/jkac078).
|
|
571
|
+
|
|
552
572
|
---
|
|
553
573
|
|
|
554
574
|
## Running the server
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Framework bump to 0.8.13 — gated tools stay visible in the operator manifest via disabledTool(), SQL gate function deny-list adopted from the framework, RequestContext slice swapped onto the framework's exported type."
|
|
3
|
+
breaking: false
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 0.4.11 — 2026-05-03
|
|
7
|
+
|
|
8
|
+
Maintenance pass on top of v0.4.10. The framework picked up three things this server was carrying locally — operator-visible disabled tools, the SQL function deny-list, and the request-context slice type — so they're swapped onto the upstream surface here. No tool surface, schema, or env-var changes for callers.
|
|
9
|
+
|
|
10
|
+
## Changed
|
|
11
|
+
|
|
12
|
+
- **Framework bump** — `@cyanheads/mcp-ts-core` `^0.8.10` → `^0.8.13`. Picks up `disabledTool()`, `SQL_GATE_REASONS` / `SqlGateReason` exports, the `DENIED_TABLE_FUNCTIONS` plus pre-EXPLAIN `assertNoDeniedFunctions` SQL-gate layer, and the `RequestContext` interface with the 0.8.12 strict-optional widening.
|
|
13
|
+
- **Gated tools stay in the operator manifest** — `src/index.ts` swaps the conditional spreads (`enableWrites ? writeToolDefinitions : []` and `canvasEnabled ? dataframeToolDefinitions : []`) for `disabledTool(d, { reason, hint })` wrappers from `@cyanheads/mcp-ts-core/tools`. Disabled tools are still skipped at registration so clients can't invoke them, but operators reading `/.well-known/mcp.json` and the HTML landing page see them with a one-line reason and an enable hint. Dataframe tools surface `Set BRAPI_CANVAS_ENABLED=true and CANVAS_PROVIDER_TYPE=duckdb to enable.`; the write surface surfaces `Set BRAPI_ENABLE_WRITES=true to enable observation submission.`. Registration-gate tests updated to assert the `__mcpDisabled` marker shape on the wrapped definition.
|
|
14
|
+
- **`brapi_dataframe_query` consumes the framework's gate-reason union** — `src/mcp-server/tools/definitions/brapi-dataframe-query.tool.ts` now imports `SQL_GATE_REASONS` and the `SqlGateReason` union from `@cyanheads/mcp-ts-core/canvas` instead of duplicating the strings locally. The `extractSqlGateReason` helper returns `SqlGateReason | undefined` so the `data.gateReason` payload stays in lockstep with the framework's gate. New gate codes (`denied_function`, `denied_function_in_plan`) flow through automatically.
|
|
15
|
+
- **`CanvasBridge.asRequestContext` uses the framework's `RequestContext` type** — `src/services/canvas-bridge/canvas-bridge.ts` drops the local `CanvasRequestContext` slice in favor of `RequestContext` imported from `@cyanheads/mcp-ts-core/utils`. The slice still has to be constructed explicitly because `RequestContext` carries an `[key: string]: unknown` index signature the strict `Context` interface lacks, so direct assignment fails despite the strict-optional widening — the construction shape is unchanged.
|
|
16
|
+
|
|
17
|
+
## Removed
|
|
18
|
+
|
|
19
|
+
- **Server-side `FORBIDDEN_SQL_FUNCTIONS` deny-list** — the regex-based pre-canvas guard for `read_json*` / `read_parquet*` / `parquet_scan` / `iceberg_scan` / `delta_scan` is removed from `src/services/canvas-bridge/canvas-bridge.ts` along with the eight unit tests that exercised it. The framework now ships a richer pre-EXPLAIN deny-list (`assertNoDeniedFunctions` + `DENIED_TABLE_FUNCTIONS`) plus a plan-walk rescan, so the local belt-and-suspenders is redundant. Disallowed function calls now surface as `denied_function` / `denied_function_in_plan` gate reasons instead of the previous `plan_operator_not_allowed` synthetic reason.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
---
|
|
2
|
+
summary: "Built-in alias registry — `cassava`, `sweetpotato`, `wheat`, and `breedbase` resolve out-of-the-box without env vars; orientation envelope now carries CC-BY attribution metadata."
|
|
3
|
+
breaking: false
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 0.4.12 — 2026-05-04
|
|
7
|
+
|
|
8
|
+
`brapi_connect` now ships with a curated registry of public BrAPI v2 endpoints, so agents can call `brapi_connect({ alias: 'cassava' })` (or `sweetpotato`, `wheat`, `breedbase`) on a fresh deployment without any env-var setup. Each builtin was probed against the live upstream surface — anonymous reads return real data and the standard `/studies`, `/germplasm`, `/variables` endpoints respond with non-trivial totals. Two servers that brapi.org/servers still lists as no-auth (`musabase.org`, `solgenomics.net`) actually require login on every endpoint and are intentionally absent.
|
|
9
|
+
|
|
10
|
+
## Added
|
|
11
|
+
|
|
12
|
+
- **Built-in known-server registry** at `src/config/builtin-aliases.ts`. Frozen list with attribution metadata (license, citation, homepage, demo flag). Resolves between per-alias env vars and `BRAPI_DEFAULT_*` so operator overrides still win and credentialed connections still work as before.
|
|
13
|
+
- **`attribution` block in the orientation envelope** — when a connection comes from a builtin, the envelope returned by `brapi_connect` and `brapi_server_info` includes `{ license, citation, homepage, isDemo? }`. CC-BY attribution propagates to the agent automatically; the formatted text output now renders an `## Attribution` section. Absent for custom env-only or agent-passed connections.
|
|
14
|
+
- **`BRAPI_BUILTIN_ALIASES_DISABLED`** opt-out env var. Comma-separated alias names (case-insensitive, whitespace-tolerant) remove specific builtins from resolution and discovery for deployments that prefer a stripped surface.
|
|
15
|
+
- **`origin: 'env' | 'builtin'`** field on `DiscoveredAlias`. The connect tool description now splits the two sources into separate sentences so agents can tell which aliases ship out-of-the-box vs which the operator pre-wired.
|
|
16
|
+
|
|
17
|
+
## Changed
|
|
18
|
+
|
|
19
|
+
- **`resolveConnectInput` precedence is four layers** (was three): agent input → per-alias env → builtin registry → default env. When the baseUrl comes from a builtin, `BRAPI_DEFAULT_*` credentials are no longer layered on top — those belong to the default server, not whatever upstream the builtin happens to point at. Per-alias credentials still apply.
|
|
20
|
+
- **README** documents the new precedence, the four shipped aliases, override behavior (`BRAPI_<ALIAS>_BASE_URL` repoints, `BRAPI_<ALIAS>_USERNAME`+`_PASSWORD` attaches auth), and the opt-out env var.
|
|
21
|
+
|
|
22
|
+
## Fixed
|
|
23
|
+
|
|
24
|
+
- **`brapi_find_studies` and `brapi_get_study` tolerate `seasons: [null]`** — the breedbase.org demo deployment serves studies with a literal null inside the seasons array, which previously caused Zod to reject the entire response. Inner element type is now `string \| null`; the format renderers and distribution computation skip null entries. New sparse-payload test case covers the breedbase shape.
|
|
25
|
+
|
|
26
|
+
## Notes
|
|
27
|
+
|
|
28
|
+
- Hosted-deployment migration: operators currently setting `BRAPI_CASSAVA_BASE_URL=https://cassavabase.org/brapi/v2` can drop that env var — the builtin covers it. `BRAPI_CASSAVA_USERNAME` / `_PASSWORD` (if set for write access) continue to work unchanged.
|
|
29
|
+
- Each Breedbase instance has its own user table — no SSO across `cassavabase.org`, `sweetpotatobase.org`, `wheat.triticeaetoolbox.org`. Write access still requires separate registration on each upstream.
|
|
@@ -39,44 +39,56 @@ export interface ResolvedConnectInput {
|
|
|
39
39
|
baseUrl: string;
|
|
40
40
|
}
|
|
41
41
|
/**
|
|
42
|
-
* Layer agent input over alias env over default env.
|
|
43
|
-
* baseUrl + auth. Throws when no baseUrl is resolvable
|
|
42
|
+
* Layer agent input over alias env over the builtin registry over default env.
|
|
43
|
+
* Returns the resolved baseUrl + auth. Throws when no baseUrl is resolvable
|
|
44
|
+
* from any layer.
|
|
44
45
|
*
|
|
45
46
|
* Precedence:
|
|
46
47
|
* 1. Explicit agent input (`baseUrl`, `auth`) wins.
|
|
47
48
|
* 2. Per-alias env vars (`BRAPI_<ALIAS>_*`).
|
|
48
|
-
* 3.
|
|
49
|
-
* 4.
|
|
49
|
+
* 3. Built-in known-server registry — see `config/builtin-aliases.ts`.
|
|
50
|
+
* 4. Default env vars (`BRAPI_DEFAULT_*`) — only when alias differs.
|
|
51
|
+
* 5. `auth` falls through to `{ mode: 'none' }`; `baseUrl` has no fallback.
|
|
52
|
+
*
|
|
53
|
+
* When the baseUrl is satisfied by a builtin, default-env auth is NOT used —
|
|
54
|
+
* default credentials belong to the default server, not whatever upstream the
|
|
55
|
+
* builtin happens to point at. Per-alias creds still apply, since those were
|
|
56
|
+
* explicitly set for this alias.
|
|
50
57
|
*/
|
|
51
58
|
export declare function resolveConnectInput(alias: string, agent: {
|
|
52
59
|
baseUrl?: string | undefined;
|
|
53
60
|
auth?: ConnectAuth | undefined;
|
|
54
61
|
}, env?: NodeJS.ProcessEnv): ResolvedConnectInput;
|
|
55
62
|
/**
|
|
56
|
-
* Summary of an alias
|
|
57
|
-
*
|
|
58
|
-
*
|
|
63
|
+
* Summary of an alias the agent can call out-of-the-box. Either pre-wired by
|
|
64
|
+
* the operator via `BRAPI_<ALIAS>_BASE_URL` (`origin: 'env'`) or shipped in the
|
|
65
|
+
* built-in known-server registry (`origin: 'builtin'`). Surfaced to the LLM
|
|
66
|
+
* via the connect tool description so agents can pick a shortcut without the
|
|
67
|
+
* human having to enumerate them.
|
|
59
68
|
*/
|
|
60
69
|
export interface DiscoveredAlias {
|
|
61
70
|
alias: string;
|
|
62
71
|
authMode: AuthMode;
|
|
63
72
|
baseUrl: string;
|
|
73
|
+
origin: 'env' | 'builtin';
|
|
64
74
|
}
|
|
65
75
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
76
|
+
* Inventory of aliases the agent can call without specifying a baseUrl. Merges
|
|
77
|
+
* env-driven entries (operator-set `BRAPI_<X>_BASE_URL`) with the built-in
|
|
78
|
+
* known-server registry. Env-set aliases win when both are present, since the
|
|
79
|
+
* resolver gives env precedence; their `origin` reflects that. Per-alias
|
|
80
|
+
* credentials still derive auth in either case, so a builtin alias with
|
|
81
|
+
* `BRAPI_<ALIAS>_USERNAME` set surfaces with the right `authMode`.
|
|
71
82
|
*
|
|
72
83
|
* Default-alias entries land first; the rest are alphabetical.
|
|
73
84
|
*/
|
|
74
85
|
export declare function discoverConfiguredAliases(env?: NodeJS.ProcessEnv): DiscoveredAlias[];
|
|
75
86
|
/**
|
|
76
87
|
* Render the discovered alias list as a sentence appended to the connect
|
|
77
|
-
* tool's description. Empty when nothing is
|
|
78
|
-
*
|
|
79
|
-
*
|
|
88
|
+
* tool's description. Empty when nothing is configured. Splits builtins from
|
|
89
|
+
* env-driven aliases so the LLM understands which work out-of-the-box vs
|
|
90
|
+
* which the operator pre-wired. Phrased so that absent aliases are never read
|
|
91
|
+
* as restricted servers: any BrAPI v2 URL stays connectable.
|
|
80
92
|
*/
|
|
81
93
|
export declare function formatConfiguredAliasesHint(aliases: DiscoveredAlias[]): string;
|
|
82
94
|
//# sourceMappingURL=alias-credentials.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alias-credentials.d.ts","sourceRoot":"","sources":["../../src/config/alias-credentials.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"alias-credentials.d.ts","sourceRoot":"","sources":["../../src/config/alias-credentials.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,qCAAqC,CAAC;AAEjF;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAiBD,iFAAiF;AACjF,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEpD;AAED,oFAAoF;AACpF,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,gBAAgB,CAQlB;AAED;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,gBAAgB,EACvB,KAAK,EAAE,MAAM,GACZ,WAAW,GAAG,SAAS,CAwCzB;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,IAAI,CAAC,EAAE,WAAW,GAAG,SAAS,CAAA;CAAE,EACvE,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,oBAAoB,CAwBtB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,KAAK,GAAG,SAAS,CAAC;CAC3B;AAID;;;;;;;;;GASG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,eAAe,EAAE,CAoCjG;AAaD;;;;;;GAMG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,eAAe,EAAE,GAAG,MAAM,CAmB9E"}
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
* @module config/alias-credentials
|
|
10
10
|
*/
|
|
11
11
|
import { validationError } from '@cyanheads/mcp-ts-core/errors';
|
|
12
|
+
import { findBuiltinAlias, listBuiltinAliases } from '../config/builtin-aliases.js';
|
|
12
13
|
const FIELD_SUFFIXES = [
|
|
13
14
|
['baseUrl', 'BASE_URL'],
|
|
14
15
|
['username', 'USERNAME'],
|
|
@@ -21,6 +22,7 @@ const FIELD_SUFFIXES = [
|
|
|
21
22
|
['oauthTokenUrl', 'OAUTH_TOKEN_URL'],
|
|
22
23
|
];
|
|
23
24
|
const DEFAULT_ALIAS = 'default';
|
|
25
|
+
const NONE_AUTH = { mode: 'none' };
|
|
24
26
|
/** Compute the env-var prefix for an alias. `my-server` → `BRAPI_MY_SERVER_`. */
|
|
25
27
|
export function aliasEnvPrefix(alias) {
|
|
26
28
|
return `BRAPI_${alias.replace(/-/g, '_').toUpperCase()}_`;
|
|
@@ -81,42 +83,53 @@ export function deriveAuthFromCredentials(creds, alias) {
|
|
|
81
83
|
return;
|
|
82
84
|
}
|
|
83
85
|
/**
|
|
84
|
-
* Layer agent input over alias env over default env.
|
|
85
|
-
* baseUrl + auth. Throws when no baseUrl is resolvable
|
|
86
|
+
* Layer agent input over alias env over the builtin registry over default env.
|
|
87
|
+
* Returns the resolved baseUrl + auth. Throws when no baseUrl is resolvable
|
|
88
|
+
* from any layer.
|
|
86
89
|
*
|
|
87
90
|
* Precedence:
|
|
88
91
|
* 1. Explicit agent input (`baseUrl`, `auth`) wins.
|
|
89
92
|
* 2. Per-alias env vars (`BRAPI_<ALIAS>_*`).
|
|
90
|
-
* 3.
|
|
91
|
-
* 4.
|
|
93
|
+
* 3. Built-in known-server registry — see `config/builtin-aliases.ts`.
|
|
94
|
+
* 4. Default env vars (`BRAPI_DEFAULT_*`) — only when alias differs.
|
|
95
|
+
* 5. `auth` falls through to `{ mode: 'none' }`; `baseUrl` has no fallback.
|
|
96
|
+
*
|
|
97
|
+
* When the baseUrl is satisfied by a builtin, default-env auth is NOT used —
|
|
98
|
+
* default credentials belong to the default server, not whatever upstream the
|
|
99
|
+
* builtin happens to point at. Per-alias creds still apply, since those were
|
|
100
|
+
* explicitly set for this alias.
|
|
92
101
|
*/
|
|
93
102
|
export function resolveConnectInput(alias, agent, env = process.env) {
|
|
94
103
|
const aliasCreds = readAliasCredentials(alias, env);
|
|
95
104
|
const defaultCreds = alias === DEFAULT_ALIAS ? aliasCreds : readAliasCredentials(DEFAULT_ALIAS, env);
|
|
96
|
-
const
|
|
105
|
+
const builtin = !agent.baseUrl && !aliasCreds.baseUrl ? findBuiltinAlias(alias, env) : undefined;
|
|
106
|
+
const baseUrl = agent.baseUrl ?? aliasCreds.baseUrl ?? builtin?.baseUrl ?? defaultCreds.baseUrl;
|
|
97
107
|
if (!baseUrl) {
|
|
98
108
|
throw validationError(`No baseUrl provided. Pass \`baseUrl\` explicitly, or set ${aliasEnvPrefix(alias)}BASE_URL${alias === DEFAULT_ALIAS ? '' : ` or ${aliasEnvPrefix(DEFAULT_ALIAS)}BASE_URL`}.`, { alias });
|
|
99
109
|
}
|
|
110
|
+
const allowDefaultAuthFallback = !builtin && alias !== DEFAULT_ALIAS;
|
|
100
111
|
const auth = agent.auth ??
|
|
101
112
|
deriveAuthFromCredentials(aliasCreds, alias) ??
|
|
102
|
-
(
|
|
103
|
-
?
|
|
104
|
-
:
|
|
105
|
-
|
|
113
|
+
(allowDefaultAuthFallback
|
|
114
|
+
? deriveAuthFromCredentials(defaultCreds, DEFAULT_ALIAS)
|
|
115
|
+
: undefined) ??
|
|
116
|
+
NONE_AUTH;
|
|
106
117
|
return { baseUrl, auth };
|
|
107
118
|
}
|
|
108
119
|
const ALIAS_BASE_URL_PATTERN = /^BRAPI_([A-Z0-9_]+)_BASE_URL$/;
|
|
109
120
|
/**
|
|
110
|
-
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
121
|
+
* Inventory of aliases the agent can call without specifying a baseUrl. Merges
|
|
122
|
+
* env-driven entries (operator-set `BRAPI_<X>_BASE_URL`) with the built-in
|
|
123
|
+
* known-server registry. Env-set aliases win when both are present, since the
|
|
124
|
+
* resolver gives env precedence; their `origin` reflects that. Per-alias
|
|
125
|
+
* credentials still derive auth in either case, so a builtin alias with
|
|
126
|
+
* `BRAPI_<ALIAS>_USERNAME` set surfaces with the right `authMode`.
|
|
115
127
|
*
|
|
116
128
|
* Default-alias entries land first; the rest are alphabetical.
|
|
117
129
|
*/
|
|
118
130
|
export function discoverConfiguredAliases(env = process.env) {
|
|
119
131
|
const result = [];
|
|
132
|
+
const seen = new Set();
|
|
120
133
|
for (const [key, value] of Object.entries(env)) {
|
|
121
134
|
const match = key.match(ALIAS_BASE_URL_PATTERN);
|
|
122
135
|
const captured = match?.[1];
|
|
@@ -124,16 +137,24 @@ export function discoverConfiguredAliases(env = process.env) {
|
|
|
124
137
|
continue;
|
|
125
138
|
const alias = captured.toLowerCase();
|
|
126
139
|
const creds = readAliasCredentials(alias, env);
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
140
|
+
result.push({
|
|
141
|
+
alias,
|
|
142
|
+
authMode: deriveModeForDiscovery(creds, alias),
|
|
143
|
+
baseUrl: value,
|
|
144
|
+
origin: 'env',
|
|
145
|
+
});
|
|
146
|
+
seen.add(alias);
|
|
147
|
+
}
|
|
148
|
+
for (const builtin of listBuiltinAliases(env)) {
|
|
149
|
+
if (seen.has(builtin.alias))
|
|
150
|
+
continue;
|
|
151
|
+
const creds = readAliasCredentials(builtin.alias, env);
|
|
152
|
+
result.push({
|
|
153
|
+
alias: builtin.alias,
|
|
154
|
+
authMode: deriveModeForDiscovery(creds, builtin.alias),
|
|
155
|
+
baseUrl: builtin.baseUrl,
|
|
156
|
+
origin: 'builtin',
|
|
157
|
+
});
|
|
137
158
|
}
|
|
138
159
|
result.sort((a, b) => {
|
|
139
160
|
if (a.alias === DEFAULT_ALIAS)
|
|
@@ -144,16 +165,37 @@ export function discoverConfiguredAliases(env = process.env) {
|
|
|
144
165
|
});
|
|
145
166
|
return result;
|
|
146
167
|
}
|
|
168
|
+
function deriveModeForDiscovery(creds, alias) {
|
|
169
|
+
try {
|
|
170
|
+
const auth = deriveAuthFromCredentials(creds, alias);
|
|
171
|
+
return auth?.mode ?? 'none';
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
// Ambiguous credential family — surface the alias as `none` so the agent
|
|
175
|
+
// still sees it; the connect call will raise the same ValidationError.
|
|
176
|
+
return 'none';
|
|
177
|
+
}
|
|
178
|
+
}
|
|
147
179
|
/**
|
|
148
180
|
* Render the discovered alias list as a sentence appended to the connect
|
|
149
|
-
* tool's description. Empty when nothing is
|
|
150
|
-
*
|
|
151
|
-
*
|
|
181
|
+
* tool's description. Empty when nothing is configured. Splits builtins from
|
|
182
|
+
* env-driven aliases so the LLM understands which work out-of-the-box vs
|
|
183
|
+
* which the operator pre-wired. Phrased so that absent aliases are never read
|
|
184
|
+
* as restricted servers: any BrAPI v2 URL stays connectable.
|
|
152
185
|
*/
|
|
153
186
|
export function formatConfiguredAliasesHint(aliases) {
|
|
154
187
|
if (aliases.length === 0)
|
|
155
188
|
return '';
|
|
156
|
-
const
|
|
157
|
-
|
|
189
|
+
const builtin = aliases.filter((a) => a.origin === 'builtin').map((a) => `\`${a.alias}\``);
|
|
190
|
+
const env = aliases.filter((a) => a.origin === 'env').map((a) => `\`${a.alias}\``);
|
|
191
|
+
const parts = [];
|
|
192
|
+
if (builtin.length > 0) {
|
|
193
|
+
parts.push(`Built-in known servers (callable with no \`baseUrl\` or \`auth\` — public BrAPI v2 endpoints): ${builtin.join(', ')}.`);
|
|
194
|
+
}
|
|
195
|
+
if (env.length > 0) {
|
|
196
|
+
parts.push(`Operator-configured aliases on this deployment (credentials and/or baseUrl read from server env vars): ${env.join(', ')}.`);
|
|
197
|
+
}
|
|
198
|
+
parts.push('Aliases are shortcuts only; any other BrAPI v2 server is reachable by passing `baseUrl` directly.');
|
|
199
|
+
return parts.join(' ');
|
|
158
200
|
}
|
|
159
201
|
//# sourceMappingURL=alias-credentials.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"alias-credentials.js","sourceRoot":"","sources":["../../src/config/alias-credentials.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"alias-credentials.js","sourceRoot":"","sources":["../../src/config/alias-credentials.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Built-in known-server registry. Curated list of public BrAPI v2
|
|
3
|
+
* endpoints that ship as default connection aliases — operators can call
|
|
4
|
+
* `brapi_connect({ alias: 'cassava' })` (or any other entry) without setting
|
|
5
|
+
* `BRAPI_<ALIAS>_BASE_URL`. Each entry carries CC-BY attribution metadata so
|
|
6
|
+
* the orientation envelope can surface license + citation alongside the data.
|
|
7
|
+
*
|
|
8
|
+
* Override behavior: env-set `BRAPI_<ALIAS>_BASE_URL` always wins over the
|
|
9
|
+
* builtin URL — the builtin is a fallback, not a lock. Per-alias credentials
|
|
10
|
+
* (`BRAPI_<ALIAS>_USERNAME` / `_PASSWORD` / etc.) layer on top of any selected
|
|
11
|
+
* baseUrl, so write workflows still need a separate registration on each
|
|
12
|
+
* upstream instance.
|
|
13
|
+
*
|
|
14
|
+
* Opt-out: comma-separated alias names in `BRAPI_BUILTIN_ALIASES_DISABLED`
|
|
15
|
+
* remove specific builtins from resolution and discovery (matched
|
|
16
|
+
* case-insensitively).
|
|
17
|
+
*
|
|
18
|
+
* @module config/builtin-aliases
|
|
19
|
+
*/
|
|
20
|
+
export interface BuiltinAlias {
|
|
21
|
+
readonly alias: string;
|
|
22
|
+
readonly baseUrl: string;
|
|
23
|
+
readonly citation: string;
|
|
24
|
+
readonly cropFocus: string;
|
|
25
|
+
readonly homepage: string;
|
|
26
|
+
readonly isDemo?: boolean;
|
|
27
|
+
readonly license: 'CC-BY';
|
|
28
|
+
readonly organizationName: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Frozen registry of known public BrAPI v2 servers. Each entry was verified
|
|
32
|
+
* against the live upstream surface — anonymous reads return real data and
|
|
33
|
+
* the standard `/studies`, `/germplasm`, `/variables` endpoints respond with
|
|
34
|
+
* non-trivial totals. Servers that flipped to an auth wall (musabase,
|
|
35
|
+
* solgenomics) are intentionally absent.
|
|
36
|
+
*/
|
|
37
|
+
export declare const BUILTIN_ALIASES: ReadonlyArray<BuiltinAlias>;
|
|
38
|
+
/**
|
|
39
|
+
* Resolve a builtin entry by alias. Case-insensitive lookup; respects the
|
|
40
|
+
* `BRAPI_BUILTIN_ALIASES_DISABLED` opt-out list. Returns `undefined` when the
|
|
41
|
+
* alias is unknown or disabled — callers fall through to the next baseUrl
|
|
42
|
+
* source (default env, then a thrown ValidationError).
|
|
43
|
+
*/
|
|
44
|
+
export declare function findBuiltinAlias(alias: string, env?: NodeJS.ProcessEnv): BuiltinAlias | undefined;
|
|
45
|
+
/**
|
|
46
|
+
* Active builtins — the registry minus any aliases listed in
|
|
47
|
+
* `BRAPI_BUILTIN_ALIASES_DISABLED`. Used by alias discovery so the connect
|
|
48
|
+
* tool description can advertise what's available out-of-the-box.
|
|
49
|
+
*/
|
|
50
|
+
export declare function listBuiltinAliases(env?: NodeJS.ProcessEnv): ReadonlyArray<BuiltinAlias>;
|
|
51
|
+
//# sourceMappingURL=builtin-aliases.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builtin-aliases.d.ts","sourceRoot":"","sources":["../../src/config/builtin-aliases.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;CACnC;AAED;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,EAAE,aAAa,CAAC,YAAY,CAsCtD,CAAC;AAmBH;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,MAAM,EACb,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,YAAY,GAAG,SAAS,CAK1B;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,aAAa,CAAC,YAAY,CAAC,CAI7B"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Built-in known-server registry. Curated list of public BrAPI v2
|
|
3
|
+
* endpoints that ship as default connection aliases — operators can call
|
|
4
|
+
* `brapi_connect({ alias: 'cassava' })` (or any other entry) without setting
|
|
5
|
+
* `BRAPI_<ALIAS>_BASE_URL`. Each entry carries CC-BY attribution metadata so
|
|
6
|
+
* the orientation envelope can surface license + citation alongside the data.
|
|
7
|
+
*
|
|
8
|
+
* Override behavior: env-set `BRAPI_<ALIAS>_BASE_URL` always wins over the
|
|
9
|
+
* builtin URL — the builtin is a fallback, not a lock. Per-alias credentials
|
|
10
|
+
* (`BRAPI_<ALIAS>_USERNAME` / `_PASSWORD` / etc.) layer on top of any selected
|
|
11
|
+
* baseUrl, so write workflows still need a separate registration on each
|
|
12
|
+
* upstream instance.
|
|
13
|
+
*
|
|
14
|
+
* Opt-out: comma-separated alias names in `BRAPI_BUILTIN_ALIASES_DISABLED`
|
|
15
|
+
* remove specific builtins from resolution and discovery (matched
|
|
16
|
+
* case-insensitively).
|
|
17
|
+
*
|
|
18
|
+
* @module config/builtin-aliases
|
|
19
|
+
*/
|
|
20
|
+
const BREEDBASE_CITATION = 'Morales et al. 2022. "Breedbase: a digital ecosystem for modern plant breeding." G3 12(7): jkac078. https://doi.org/10.1093/g3journal/jkac078';
|
|
21
|
+
/**
|
|
22
|
+
* Frozen registry of known public BrAPI v2 servers. Each entry was verified
|
|
23
|
+
* against the live upstream surface — anonymous reads return real data and
|
|
24
|
+
* the standard `/studies`, `/germplasm`, `/variables` endpoints respond with
|
|
25
|
+
* non-trivial totals. Servers that flipped to an auth wall (musabase,
|
|
26
|
+
* solgenomics) are intentionally absent.
|
|
27
|
+
*/
|
|
28
|
+
export const BUILTIN_ALIASES = Object.freeze([
|
|
29
|
+
Object.freeze({
|
|
30
|
+
alias: 'cassava',
|
|
31
|
+
baseUrl: 'https://cassavabase.org/brapi/v2',
|
|
32
|
+
homepage: 'https://cassavabase.org/',
|
|
33
|
+
organizationName: 'Boyce Thompson Institute',
|
|
34
|
+
cropFocus: 'Cassava',
|
|
35
|
+
license: 'CC-BY',
|
|
36
|
+
citation: BREEDBASE_CITATION,
|
|
37
|
+
}),
|
|
38
|
+
Object.freeze({
|
|
39
|
+
alias: 'sweetpotato',
|
|
40
|
+
baseUrl: 'https://sweetpotatobase.org/brapi/v2',
|
|
41
|
+
homepage: 'https://sweetpotatobase.org/',
|
|
42
|
+
organizationName: 'Boyce Thompson Institute',
|
|
43
|
+
cropFocus: 'SweetPotato',
|
|
44
|
+
license: 'CC-BY',
|
|
45
|
+
citation: BREEDBASE_CITATION,
|
|
46
|
+
}),
|
|
47
|
+
Object.freeze({
|
|
48
|
+
alias: 'wheat',
|
|
49
|
+
baseUrl: 'https://wheat.triticeaetoolbox.org/brapi/v2',
|
|
50
|
+
homepage: 'https://wheat.triticeaetoolbox.org/',
|
|
51
|
+
organizationName: 'Triticeae Toolbox (T3)',
|
|
52
|
+
cropFocus: 'Wheat',
|
|
53
|
+
license: 'CC-BY',
|
|
54
|
+
citation: BREEDBASE_CITATION,
|
|
55
|
+
}),
|
|
56
|
+
Object.freeze({
|
|
57
|
+
alias: 'breedbase',
|
|
58
|
+
baseUrl: 'https://breedbase.org/brapi/v2',
|
|
59
|
+
homepage: 'https://breedbase.org/',
|
|
60
|
+
organizationName: 'Boyce Thompson Institute',
|
|
61
|
+
cropFocus: 'Demo (sample data)',
|
|
62
|
+
license: 'CC-BY',
|
|
63
|
+
citation: BREEDBASE_CITATION,
|
|
64
|
+
isDemo: true,
|
|
65
|
+
}),
|
|
66
|
+
]);
|
|
67
|
+
const DISABLED_ENV_VAR = 'BRAPI_BUILTIN_ALIASES_DISABLED';
|
|
68
|
+
/**
|
|
69
|
+
* Parse the comma-separated disabled list from env. Whitespace tolerant,
|
|
70
|
+
* case-insensitive — entries are lowercased to match alias keys.
|
|
71
|
+
*/
|
|
72
|
+
function readDisabledSet(env) {
|
|
73
|
+
const raw = env[DISABLED_ENV_VAR];
|
|
74
|
+
if (!raw)
|
|
75
|
+
return new Set();
|
|
76
|
+
const out = new Set();
|
|
77
|
+
for (const part of raw.split(',')) {
|
|
78
|
+
const trimmed = part.trim().toLowerCase();
|
|
79
|
+
if (trimmed)
|
|
80
|
+
out.add(trimmed);
|
|
81
|
+
}
|
|
82
|
+
return out;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Resolve a builtin entry by alias. Case-insensitive lookup; respects the
|
|
86
|
+
* `BRAPI_BUILTIN_ALIASES_DISABLED` opt-out list. Returns `undefined` when the
|
|
87
|
+
* alias is unknown or disabled — callers fall through to the next baseUrl
|
|
88
|
+
* source (default env, then a thrown ValidationError).
|
|
89
|
+
*/
|
|
90
|
+
export function findBuiltinAlias(alias, env = process.env) {
|
|
91
|
+
const key = alias.toLowerCase();
|
|
92
|
+
const disabled = readDisabledSet(env);
|
|
93
|
+
if (disabled.has(key))
|
|
94
|
+
return;
|
|
95
|
+
return BUILTIN_ALIASES.find((entry) => entry.alias === key);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Active builtins — the registry minus any aliases listed in
|
|
99
|
+
* `BRAPI_BUILTIN_ALIASES_DISABLED`. Used by alias discovery so the connect
|
|
100
|
+
* tool description can advertise what's available out-of-the-box.
|
|
101
|
+
*/
|
|
102
|
+
export function listBuiltinAliases(env = process.env) {
|
|
103
|
+
const disabled = readDisabledSet(env);
|
|
104
|
+
if (disabled.size === 0)
|
|
105
|
+
return BUILTIN_ALIASES;
|
|
106
|
+
return BUILTIN_ALIASES.filter((entry) => !disabled.has(entry.alias));
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=builtin-aliases.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"builtin-aliases.js","sourceRoot":"","sources":["../../src/config/builtin-aliases.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,kBAAkB,GACtB,+IAA+I,CAAC;AAalJ;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,eAAe,GAAgC,MAAM,CAAC,MAAM,CAAC;IACxE,MAAM,CAAC,MAAM,CAAC;QACZ,KAAK,EAAE,SAAS;QAChB,OAAO,EAAE,kCAAkC;QAC3C,QAAQ,EAAE,0BAA0B;QACpC,gBAAgB,EAAE,0BAA0B;QAC5C,SAAS,EAAE,SAAS;QACpB,OAAO,EAAE,OAAO;QAChB,QAAQ,EAAE,kBAAkB;KAC7B,CAAC;IACF,MAAM,CAAC,MAAM,CAAC;QACZ,KAAK,EAAE,aAAa;QACpB,OAAO,EAAE,sCAAsC;QAC/C,QAAQ,EAAE,8BAA8B;QACxC,gBAAgB,EAAE,0BAA0B;QAC5C,SAAS,EAAE,aAAa;QACxB,OAAO,EAAE,OAAO;QAChB,QAAQ,EAAE,kBAAkB;KAC7B,CAAC;IACF,MAAM,CAAC,MAAM,CAAC;QACZ,KAAK,EAAE,OAAO;QACd,OAAO,EAAE,6CAA6C;QACtD,QAAQ,EAAE,qCAAqC;QAC/C,gBAAgB,EAAE,wBAAwB;QAC1C,SAAS,EAAE,OAAO;QAClB,OAAO,EAAE,OAAO;QAChB,QAAQ,EAAE,kBAAkB;KAC7B,CAAC;IACF,MAAM,CAAC,MAAM,CAAC;QACZ,KAAK,EAAE,WAAW;QAClB,OAAO,EAAE,gCAAgC;QACzC,QAAQ,EAAE,wBAAwB;QAClC,gBAAgB,EAAE,0BAA0B;QAC5C,SAAS,EAAE,oBAAoB;QAC/B,OAAO,EAAE,OAAO;QAChB,QAAQ,EAAE,kBAAkB;QAC5B,MAAM,EAAE,IAAI;KACb,CAAC;CACH,CAAC,CAAC;AAEH,MAAM,gBAAgB,GAAG,gCAAgC,CAAC;AAE1D;;;GAGG;AACH,SAAS,eAAe,CAAC,GAAsB;IAC7C,MAAM,GAAG,GAAG,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAClC,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,GAAG,EAAE,CAAC;IAC3B,MAAM,GAAG,GAAG,IAAI,GAAG,EAAU,CAAC;IAC9B,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;QAC1C,IAAI,OAAO;YAAE,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAC9B,KAAa,EACb,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,GAAG,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAChC,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC;QAAE,OAAO;IAC9B,OAAO,eAAe,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,GAAG,CAAC,CAAC;AAC9D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAChC,MAAyB,OAAO,CAAC,GAAG;IAEpC,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IACtC,IAAI,QAAQ,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,eAAe,CAAC;IAChD,OAAO,eAAe,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;AACvE,CAAC"}
|