@cyanheads/brapi-mcp-server 0.6.4 → 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.
Files changed (43) hide show
  1. package/CLAUDE.md +11 -4
  2. package/README.md +7 -3
  3. package/changelog/0.7.x/0.7.0.md +23 -0
  4. package/dist/index.js +2 -0
  5. package/dist/index.js.map +1 -1
  6. package/dist/mcp-server/resources/definitions/brapi-variable.resource.d.ts +30 -0
  7. package/dist/mcp-server/resources/definitions/brapi-variable.resource.d.ts.map +1 -0
  8. package/dist/mcp-server/resources/definitions/brapi-variable.resource.js +78 -0
  9. package/dist/mcp-server/resources/definitions/brapi-variable.resource.js.map +1 -0
  10. package/dist/mcp-server/tools/definitions/brapi-build-phenotype-matrix.tool.d.ts +81 -0
  11. package/dist/mcp-server/tools/definitions/brapi-build-phenotype-matrix.tool.d.ts.map +1 -0
  12. package/dist/mcp-server/tools/definitions/brapi-build-phenotype-matrix.tool.js +366 -0
  13. package/dist/mcp-server/tools/definitions/brapi-build-phenotype-matrix.tool.js.map +1 -0
  14. package/dist/mcp-server/tools/definitions/brapi-export-genotype-matrix.tool.d.ts +88 -0
  15. package/dist/mcp-server/tools/definitions/brapi-export-genotype-matrix.tool.d.ts.map +1 -0
  16. package/dist/mcp-server/tools/definitions/brapi-export-genotype-matrix.tool.js +494 -0
  17. package/dist/mcp-server/tools/definitions/brapi-export-genotype-matrix.tool.js.map +1 -0
  18. package/dist/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.d.ts.map +1 -1
  19. package/dist/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.js +17 -93
  20. package/dist/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.js.map +1 -1
  21. package/dist/mcp-server/tools/definitions/brapi-germplasm-performance.tool.d.ts +60 -0
  22. package/dist/mcp-server/tools/definitions/brapi-germplasm-performance.tool.d.ts.map +1 -0
  23. package/dist/mcp-server/tools/definitions/brapi-germplasm-performance.tool.js +416 -0
  24. package/dist/mcp-server/tools/definitions/brapi-germplasm-performance.tool.js.map +1 -0
  25. package/dist/mcp-server/tools/definitions/index.d.ts +148 -0
  26. package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -1
  27. package/dist/mcp-server/tools/definitions/index.js +6 -0
  28. package/dist/mcp-server/tools/definitions/index.js.map +1 -1
  29. package/dist/mcp-server/tools/shared/canvas-columns.d.ts +32 -0
  30. package/dist/mcp-server/tools/shared/canvas-columns.d.ts.map +1 -0
  31. package/dist/mcp-server/tools/shared/canvas-columns.js +98 -0
  32. package/dist/mcp-server/tools/shared/canvas-columns.js.map +1 -0
  33. package/dist/mcp-server/tools/shared/genotype-calls.d.ts +81 -0
  34. package/dist/mcp-server/tools/shared/genotype-calls.d.ts.map +1 -0
  35. package/dist/mcp-server/tools/shared/genotype-calls.js +172 -0
  36. package/dist/mcp-server/tools/shared/genotype-calls.js.map +1 -0
  37. package/dist/mcp-server/tools/shared/observations.d.ts +87 -0
  38. package/dist/mcp-server/tools/shared/observations.d.ts.map +1 -0
  39. package/dist/mcp-server/tools/shared/observations.js +285 -0
  40. package/dist/mcp-server/tools/shared/observations.js.map +1 -0
  41. package/manifest.json +1 -1
  42. package/package.json +3 -3
  43. package/server.json +3 -3
@@ -0,0 +1 @@
1
+ {"version":3,"file":"genotype-calls.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/shared/genotype-calls.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * @fileoverview Shared observation-pull logic for the phenotype tools
3
+ * (`brapi_build_phenotype_matrix`, `brapi_germplasm_performance`). Owns the
4
+ * study-anchored observation collection strategy and the raw/normalized row
5
+ * shapes, so both tools pull observations identically without duplicating the
6
+ * server-dependent fallback chain.
7
+ *
8
+ * Observation pull strategy (server-dependent), per study:
9
+ * 1. Prefer `/observations?studyDbId=…` (BrAPI spec path).
10
+ * 2. Fall back to `/observationunits?studyDbId=…` with embedded
11
+ * `observations[]` arrays when `/observations` returns empty or the dialect
12
+ * drops the study filter — required for the BrAPI Community Test Server,
13
+ * where `/observations?studyDbId` is not honored.
14
+ * 3. When units carry `germplasmDbId`s but no embedded observations, pull
15
+ * `/observations?germplasmDbId=…` per germplasm and filter back to the
16
+ * study — stays study-anchored without an unbounded scan.
17
+ *
18
+ * `pullStudyObservations` returns `null` only when no usable observation path
19
+ * exists for the study (caller throws its typed `no_observation_path` error);
20
+ * an empty array means the paths exist but yielded no rows.
21
+ *
22
+ * @module mcp-server/tools/shared/observations
23
+ */
24
+ import type { Context } from '@cyanheads/mcp-ts-core';
25
+ import type { ServerConfig } from '../../../config/server-config.js';
26
+ import { type BrapiClient } from '../../../services/brapi-client/index.js';
27
+ import type { BrapiDialect } from '../../../services/brapi-dialect/index.js';
28
+ import type { CallDescriptor } from '../../../services/capability-registry/types.js';
29
+ import type { RegisteredServer } from '../../../services/server-registry/index.js';
30
+ /** Raw BrAPI `/observations` row shape (passthrough). */
31
+ export interface RawObservationRow {
32
+ germplasmDbId?: string | null;
33
+ germplasmName?: string | null;
34
+ observationDbId?: string | null;
35
+ observationVariableDbId?: string | null;
36
+ observationVariableName?: string | null;
37
+ season?: unknown;
38
+ seasonDbId?: string | null;
39
+ studyDbId?: string | null;
40
+ value?: string | null;
41
+ [key: string]: unknown;
42
+ }
43
+ /** Normalized observation — required fields are non-empty strings after extraction. */
44
+ export interface NormObs {
45
+ germplasmDbId: string;
46
+ germplasmName: string;
47
+ observationVariableDbId: string;
48
+ observationVariableName: string;
49
+ /** Human season label (`"spring 2013"` / seasonDbId), when the row carries one. */
50
+ season?: string;
51
+ studyDbId: string;
52
+ value: string;
53
+ }
54
+ /** Filters that scope an observation pull beyond the study anchor. */
55
+ export interface ObservationPullFilters {
56
+ extraFilters?: Record<string, unknown> | undefined;
57
+ germplasm?: string[] | undefined;
58
+ variables?: string[] | undefined;
59
+ }
60
+ export interface PullStudyObservationsArgs {
61
+ client: BrapiClient;
62
+ config: ServerConfig;
63
+ connection: RegisteredServer;
64
+ ctx: Context;
65
+ dialect: BrapiDialect;
66
+ input: ObservationPullFilters;
67
+ loadLimit: number;
68
+ profile: Record<string, CallDescriptor>;
69
+ studyDbId: string;
70
+ warnings: string[];
71
+ }
72
+ /**
73
+ * Collect observations for a single study, trying `/observations` first and
74
+ * falling back to `/observationunits` (embedded, then germplasm-anchored).
75
+ * Returns `null` when no usable path exists; `[]` when paths exist but are
76
+ * empty.
77
+ */
78
+ export declare function pullStudyObservations(args: PullStudyObservationsArgs): Promise<NormObs[] | null>;
79
+ /** Normalise a raw /observations row; drops rows missing any required field. */
80
+ export declare function normalizeObsRow(row: RawObservationRow): NormObs | null;
81
+ /**
82
+ * Derive a human season label from a BrAPI observation row. Servers carry
83
+ * season either as a nested object (`{ seasonName, year, seasonDbId }`) or a
84
+ * flat `seasonDbId` string. Returns undefined when neither is present.
85
+ */
86
+ export declare function seasonLabel(row: RawObservationRow): string | undefined;
87
+ //# sourceMappingURL=observations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observations.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/shared/observations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,KAAK,WAAW,EAAuB,MAAM,kCAAkC,CAAC;AACzF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yCAAyC,CAAC;AAC9E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAQ5E,yDAAyD;AACzD,MAAM,WAAW,iBAAiB;IAChC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,uBAAuB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,uBAAuB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACxC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,uFAAuF;AACvF,MAAM,WAAW,OAAO;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,uBAAuB,EAAE,MAAM,CAAC;IAChC,uBAAuB,EAAE,MAAM,CAAC;IAChC,mFAAmF;IACnF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,sEAAsE;AACtE,MAAM,WAAW,sBAAsB;IACrC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACnD,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;CAClC;AAED,MAAM,WAAW,yBAAyB;IACxC,MAAM,EAAE,WAAW,CAAC;IACpB,MAAM,EAAE,YAAY,CAAC;IACrB,UAAU,EAAE,gBAAgB,CAAC;IAC7B,GAAG,EAAE,OAAO,CAAC;IACb,OAAO,EAAE,YAAY,CAAC;IACtB,KAAK,EAAE,sBAAsB,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE,yBAAyB,GAC9B,OAAO,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAyH3B;AAyKD,gFAAgF;AAChF,wBAAgB,eAAe,CAAC,GAAG,EAAE,iBAAiB,GAAG,OAAO,GAAG,IAAI,CAuBtE;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,iBAAiB,GAAG,MAAM,GAAG,SAAS,CAetE"}
@@ -0,0 +1,285 @@
1
+ /**
2
+ * @fileoverview Shared observation-pull logic for the phenotype tools
3
+ * (`brapi_build_phenotype_matrix`, `brapi_germplasm_performance`). Owns the
4
+ * study-anchored observation collection strategy and the raw/normalized row
5
+ * shapes, so both tools pull observations identically without duplicating the
6
+ * server-dependent fallback chain.
7
+ *
8
+ * Observation pull strategy (server-dependent), per study:
9
+ * 1. Prefer `/observations?studyDbId=…` (BrAPI spec path).
10
+ * 2. Fall back to `/observationunits?studyDbId=…` with embedded
11
+ * `observations[]` arrays when `/observations` returns empty or the dialect
12
+ * drops the study filter — required for the BrAPI Community Test Server,
13
+ * where `/observations?studyDbId` is not honored.
14
+ * 3. When units carry `germplasmDbId`s but no embedded observations, pull
15
+ * `/observations?germplasmDbId=…` per germplasm and filter back to the
16
+ * study — stays study-anchored without an unbounded scan.
17
+ *
18
+ * `pullStudyObservations` returns `null` only when no usable observation path
19
+ * exists for the study (caller throws its typed `no_observation_path` error);
20
+ * an empty array means the paths exist but yielded no rows.
21
+ *
22
+ * @module mcp-server/tools/shared/observations
23
+ */
24
+ import { isDialectAllDropped } from '../../../services/brapi-client/index.js';
25
+ import { companionRequestOptions, extractRows, mergeFilters, } from './find-helpers.js';
26
+ /**
27
+ * Collect observations for a single study, trying `/observations` first and
28
+ * falling back to `/observationunits` (embedded, then germplasm-anchored).
29
+ * Returns `null` when no usable path exists; `[]` when paths exist but are
30
+ * empty.
31
+ */
32
+ export async function pullStudyObservations(args) {
33
+ const { studyDbId, input, client, connection, dialect, config, loadLimit, warnings, ctx } = args;
34
+ // Build named filters for observations endpoint
35
+ const namedFilters = {
36
+ studyDbIds: [studyDbId],
37
+ };
38
+ if (input.variables?.length)
39
+ namedFilters.observationVariableDbIds = input.variables;
40
+ if (input.germplasm?.length)
41
+ namedFilters.germplasmDbIds = input.germplasm;
42
+ const merged = mergeFilters(namedFilters, input.extraFilters, warnings);
43
+ // Apply dialect (plurals → singulars on SGN-family servers)
44
+ const adapted = dialect.adaptGetFilters('observations', merged);
45
+ warnings.push(...adapted.warnings);
46
+ // When the dialect drops ALL filters for /observations (known case: the
47
+ // brapi-test server doesn't honor studyDbId on /observations at all), skip
48
+ // the observations path entirely and go straight to the observationunits
49
+ // fallback rather than making an unscoped request.
50
+ const obsFiltersDropped = adapted.dropped.length > 0 && Object.keys(adapted.filters).length === 0;
51
+ const obsFilters = adapted.filters;
52
+ // ---- Path 1: /observations ----
53
+ const supportsObservations = supportsGet(args.profile, 'observations') && !obsFiltersDropped;
54
+ if (supportsObservations) {
55
+ const obs = await fetchObservationsPath(client, connection, dialect, config, obsFilters, loadLimit, ctx);
56
+ if (obs !== null && obs.length > 0) {
57
+ return obs;
58
+ }
59
+ if (obs !== null && obs.length === 0) {
60
+ // Server responded with empty for this study — note it and try fallback
61
+ warnings.push(`Study '${studyDbId}': /observations returned 0 rows — trying /observationunits fallback.`);
62
+ }
63
+ }
64
+ else if (obsFiltersDropped) {
65
+ warnings.push(`Study '${studyDbId}': dialect '${dialect.id}' drops all study filters for /observations — using /observationunits fallback.`);
66
+ }
67
+ // ---- Path 2: /observationunits fallback ----
68
+ // Two sub-strategies:
69
+ // 2a. Units embed observations[] arrays — extract directly.
70
+ // 2b. Units carry germplasmDbIds but observations[] is null — pull
71
+ // /observations?germplasmDbId=X per germplasm found in the study.
72
+ const supportsObsUnits = supportsGet(args.profile, 'observationunits');
73
+ if (supportsObsUnits) {
74
+ const unitResult = await fetchObservationUnitsRaw(client, connection, dialect, config, studyDbId, loadLimit, ctx);
75
+ if (unitResult !== null) {
76
+ // 2a: check for embedded observations
77
+ const embeddedObs = extractEmbeddedObservations(unitResult, studyDbId);
78
+ if (embeddedObs.length > 0) {
79
+ warnings.push(`Study '${studyDbId}': Using /observationunits embedded observations[] fallback.`);
80
+ return embeddedObs;
81
+ }
82
+ // 2b: germplasm-anchored pull — units have germplasmDbIds, use them
83
+ let germplasmIds = [
84
+ ...new Set(unitResult
85
+ .map((u) => u.germplasmDbId)
86
+ .filter((id) => typeof id === 'string' && id.length > 0)),
87
+ ];
88
+ // When the caller scoped to specific germplasm, pull only those — avoids
89
+ // an O(all-germplasm-in-study) fan-out for single-germplasm callers (#9).
90
+ if (input.germplasm?.length) {
91
+ const want = new Set(input.germplasm);
92
+ germplasmIds = germplasmIds.filter((g) => want.has(g));
93
+ }
94
+ if (germplasmIds.length > 0) {
95
+ const germObs = await fetchObservationsByGermplasm(client, connection, dialect, config, germplasmIds, studyDbId, loadLimit, ctx);
96
+ if (germObs !== null && germObs.length > 0) {
97
+ warnings.push(`Study '${studyDbId}': Used /observationunits → /observations?germplasmDbId fallback because studyDbId filter is not honored on /observations.`);
98
+ return germObs;
99
+ }
100
+ }
101
+ }
102
+ }
103
+ // Neither path yielded data. Distinguish "no path" from "empty".
104
+ if (!supportsObservations && !obsFiltersDropped && !supportsObsUnits) {
105
+ return null; // caller throws typed error
106
+ }
107
+ // Paths exist but all returned empty — treat as empty (not an error)
108
+ warnings.push(`Study '${studyDbId}': No observations found via /observations or /observationunits.`);
109
+ return [];
110
+ }
111
+ function supportsGet(profile, service) {
112
+ const descriptor = profile[service];
113
+ if (!descriptor)
114
+ return false;
115
+ if (!descriptor.methods || descriptor.methods.length === 0)
116
+ return true;
117
+ return descriptor.methods.includes('GET');
118
+ }
119
+ /** Fetch from /observations with study-anchored filters. Returns null on error. */
120
+ async function fetchObservationsPath(client, connection, dialect, config, filters, pageSize, ctx) {
121
+ try {
122
+ const opts = companionRequestOptions(connection, dialect, config, [], {
123
+ ...filters,
124
+ pageSize,
125
+ });
126
+ const envelope = await client.get(connection.baseUrl, '/observations', ctx, opts);
127
+ const rows = extractRows(envelope.result);
128
+ return rows.flatMap(normalizeObsRow).filter(Boolean);
129
+ }
130
+ catch (err) {
131
+ if (isDialectAllDropped(err))
132
+ throw err;
133
+ return null;
134
+ }
135
+ }
136
+ /** Fetch raw observationunit records (without extracting observations). Returns null on error. */
137
+ async function fetchObservationUnitsRaw(client, connection, dialect, config, studyDbId, pageSize, ctx) {
138
+ try {
139
+ const rawFilters = { studyDbIds: [studyDbId] };
140
+ const adapted = dialect.adaptGetFilters('observationunits', rawFilters);
141
+ const obsUnitFilters = adapted.filters;
142
+ const opts = companionRequestOptions(connection, dialect, config, [], {
143
+ ...obsUnitFilters,
144
+ pageSize,
145
+ });
146
+ const envelope = await client.get(connection.baseUrl, '/observationunits', ctx, opts);
147
+ return extractRows(envelope.result);
148
+ }
149
+ catch (err) {
150
+ if (isDialectAllDropped(err))
151
+ throw err;
152
+ return null;
153
+ }
154
+ }
155
+ /** Extract embedded observations[] from observationunit records (strategy 2a). */
156
+ function extractEmbeddedObservations(units, studyDbId) {
157
+ const obs = [];
158
+ for (const unit of units) {
159
+ const unitStudyDbId = unit.studyDbId ?? studyDbId;
160
+ const unitGermplasmDbId = unit.germplasmDbId ?? 'unknown';
161
+ const unitGermplasmName = typeof unit.germplasmName === 'string' && unit.germplasmName.length > 0
162
+ ? unit.germplasmName
163
+ : unitGermplasmDbId;
164
+ const embedded = unit.observations;
165
+ if (!Array.isArray(embedded))
166
+ continue;
167
+ for (const raw of embedded) {
168
+ if (!raw || typeof raw !== 'object')
169
+ continue;
170
+ const r = raw;
171
+ const varId = r.observationVariableDbId ?? null;
172
+ const val = r.value ?? null;
173
+ if (!varId || val === null || val === undefined)
174
+ continue;
175
+ const season = seasonLabel(r);
176
+ obs.push({
177
+ germplasmDbId: unitGermplasmDbId,
178
+ germplasmName: unitGermplasmName,
179
+ observationVariableDbId: String(varId),
180
+ observationVariableName: typeof r.observationVariableName === 'string' && r.observationVariableName.length > 0
181
+ ? r.observationVariableName
182
+ : String(varId),
183
+ studyDbId: unitStudyDbId,
184
+ value: String(val),
185
+ ...(season ? { season } : {}),
186
+ });
187
+ }
188
+ }
189
+ return obs;
190
+ }
191
+ /**
192
+ * Pull observations anchored by germplasmDbId (strategy 2b). Used when
193
+ * studyDbId filter is not honored on /observations but we know germplasmDbIds
194
+ * in the study from the observationunits response. Filters results to only
195
+ * observations for the target study.
196
+ */
197
+ async function fetchObservationsByGermplasm(client, connection, dialect, config, germplasmIds, studyDbId, pageSize, ctx) {
198
+ try {
199
+ // Pull per germplasm to stay study-anchored. Bound by pageSize per call.
200
+ // For wide queries this is O(germplasmCount) requests but avoids an
201
+ // unbounded full-table scan on the observations endpoint.
202
+ const allObs = [];
203
+ for (const germId of germplasmIds) {
204
+ const rawFilters = { germplasmDbIds: [germId] };
205
+ const adapted = dialect.adaptGetFilters('observations', rawFilters);
206
+ // Skip if the germplasm filter is also dropped
207
+ if (adapted.dropped.length > 0 && Object.keys(adapted.filters).length === 0)
208
+ continue;
209
+ const opts = companionRequestOptions(connection, dialect, config, [], {
210
+ ...adapted.filters,
211
+ pageSize,
212
+ });
213
+ try {
214
+ const envelope = await client.get(connection.baseUrl, '/observations', ctx, opts);
215
+ const rows = extractRows(envelope.result);
216
+ // Filter to only observations for the target study
217
+ for (const row of rows) {
218
+ if (row.studyDbId !== studyDbId)
219
+ continue;
220
+ const norm = normalizeObsRow(row);
221
+ if (norm)
222
+ allObs.push(norm);
223
+ }
224
+ }
225
+ catch { }
226
+ }
227
+ return allObs;
228
+ }
229
+ catch (err) {
230
+ if (isDialectAllDropped(err))
231
+ throw err;
232
+ return null;
233
+ }
234
+ }
235
+ /** Normalise a raw /observations row; drops rows missing any required field. */
236
+ export function normalizeObsRow(row) {
237
+ const varId = row.observationVariableDbId ?? null;
238
+ const germId = row.germplasmDbId ?? null;
239
+ const studyId = row.studyDbId ?? null;
240
+ const val = row.value ?? null;
241
+ if (!varId || !germId || !studyId || val === null || val === undefined)
242
+ return null;
243
+ const norm = {
244
+ germplasmDbId: String(germId),
245
+ germplasmName: typeof row.germplasmName === 'string' && row.germplasmName.length > 0
246
+ ? row.germplasmName
247
+ : String(germId),
248
+ observationVariableDbId: String(varId),
249
+ observationVariableName: typeof row.observationVariableName === 'string' && row.observationVariableName.length > 0
250
+ ? row.observationVariableName
251
+ : String(varId),
252
+ studyDbId: String(studyId),
253
+ value: String(val),
254
+ };
255
+ const season = seasonLabel(row);
256
+ if (season)
257
+ norm.season = season;
258
+ return norm;
259
+ }
260
+ /**
261
+ * Derive a human season label from a BrAPI observation row. Servers carry
262
+ * season either as a nested object (`{ seasonName, year, seasonDbId }`) or a
263
+ * flat `seasonDbId` string. Returns undefined when neither is present.
264
+ */
265
+ export function seasonLabel(row) {
266
+ const s = row.season;
267
+ if (s && typeof s === 'object') {
268
+ const so = s;
269
+ const name = typeof so.seasonName === 'string' && so.seasonName.length > 0 ? so.seasonName : undefined;
270
+ const year = typeof so.year === 'number' ? so.year : undefined;
271
+ if (name && year !== undefined)
272
+ return `${name} ${year}`;
273
+ if (name)
274
+ return name;
275
+ if (typeof so.seasonDbId === 'string' && so.seasonDbId.length > 0)
276
+ return so.seasonDbId;
277
+ }
278
+ else if (typeof s === 'string' && s.length > 0) {
279
+ return s;
280
+ }
281
+ if (typeof row.seasonDbId === 'string' && row.seasonDbId.length > 0)
282
+ return row.seasonDbId;
283
+ return;
284
+ }
285
+ //# sourceMappingURL=observations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observations.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/shared/observations.ts"],"names":[],"mappings":"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"}
package/manifest.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "manifest_version": "0.3",
3
3
  "name": "brapi-mcp-server",
4
- "version": "0.6.4",
4
+ "version": "0.7.0",
5
5
  "description": "Collaborative BrAPI v2.1 MCP workspace — studies, germplasm, genotypes across Breedbase, T3, more.",
6
6
  "author": {
7
7
  "name": "cyanheads"
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@cyanheads/brapi-mcp-server",
3
3
  "mcpName": "io.github.cyanheads/brapi-mcp-server",
4
- "version": "0.6.4",
4
+ "version": "0.7.0",
5
5
  "description": "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.",
6
6
  "author": "Casey Hand @cyanheads (https://github.com/cyanheads/brapi-mcp-server#readme)",
7
7
  "type": "module",
@@ -81,7 +81,7 @@
81
81
  },
82
82
  "dependencies": {
83
83
  "@cyanheads/mcp-ts-core": "^0.9.16",
84
- "@duckdb/node-api": "^1.5.3-r.2",
84
+ "@duckdb/node-api": "^1.5.3-r.3",
85
85
  "pino-pretty": "^13.1.3",
86
86
  "zod": "^4.4.3"
87
87
  },
@@ -92,6 +92,6 @@
92
92
  "ignore": "^7.0.5",
93
93
  "tsc-alias": "^1.8.17",
94
94
  "typescript": "^6.0.3",
95
- "vitest": "^4.1.7"
95
+ "vitest": "^4.1.8"
96
96
  }
97
97
  }
package/server.json CHANGED
@@ -6,14 +6,14 @@
6
6
  "url": "https://github.com/cyanheads/brapi-mcp-server",
7
7
  "source": "github"
8
8
  },
9
- "version": "0.6.4",
9
+ "version": "0.7.0",
10
10
  "packages": [
11
11
  {
12
12
  "registryType": "npm",
13
13
  "registryBaseUrl": "https://registry.npmjs.org",
14
14
  "identifier": "@cyanheads/brapi-mcp-server",
15
15
  "runtimeHint": "bun",
16
- "version": "0.6.4",
16
+ "version": "0.7.0",
17
17
  "packageArguments": [
18
18
  { "type": "positional", "value": "run" },
19
19
  { "type": "positional", "value": "start:stdio" }
@@ -49,7 +49,7 @@
49
49
  "registryBaseUrl": "https://registry.npmjs.org",
50
50
  "identifier": "@cyanheads/brapi-mcp-server",
51
51
  "runtimeHint": "bun",
52
- "version": "0.6.4",
52
+ "version": "0.7.0",
53
53
  "packageArguments": [
54
54
  { "type": "positional", "value": "run" },
55
55
  { "type": "positional", "value": "start:http" }