@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.
Files changed (106) hide show
  1. package/CLAUDE.md +11 -4
  2. package/README.md +7 -3
  3. package/changelog/0.6.x/0.6.4.md +14 -0
  4. package/changelog/0.7.x/0.7.0.md +23 -0
  5. package/changelog/template.md +1 -1
  6. package/dist/index.js +2 -0
  7. package/dist/index.js.map +1 -1
  8. package/dist/mcp-server/resources/definitions/brapi-variable.resource.d.ts +30 -0
  9. package/dist/mcp-server/resources/definitions/brapi-variable.resource.d.ts.map +1 -0
  10. package/dist/mcp-server/resources/definitions/brapi-variable.resource.js +78 -0
  11. package/dist/mcp-server/resources/definitions/brapi-variable.resource.js.map +1 -0
  12. package/dist/mcp-server/tools/definitions/brapi-build-phenotype-matrix.tool.d.ts +81 -0
  13. package/dist/mcp-server/tools/definitions/brapi-build-phenotype-matrix.tool.d.ts.map +1 -0
  14. package/dist/mcp-server/tools/definitions/brapi-build-phenotype-matrix.tool.js +366 -0
  15. package/dist/mcp-server/tools/definitions/brapi-build-phenotype-matrix.tool.js.map +1 -0
  16. package/dist/mcp-server/tools/definitions/brapi-connect.tool.d.ts +1 -1
  17. package/dist/mcp-server/tools/definitions/brapi-connect.tool.d.ts.map +1 -1
  18. package/dist/mcp-server/tools/definitions/brapi-dataframe-describe.tool.d.ts +1 -1
  19. package/dist/mcp-server/tools/definitions/brapi-dataframe-describe.tool.d.ts.map +1 -1
  20. package/dist/mcp-server/tools/definitions/brapi-dataframe-drop.tool.d.ts +1 -1
  21. package/dist/mcp-server/tools/definitions/brapi-dataframe-drop.tool.d.ts.map +1 -1
  22. package/dist/mcp-server/tools/definitions/brapi-dataframe-export.tool.d.ts +1 -1
  23. package/dist/mcp-server/tools/definitions/brapi-dataframe-export.tool.d.ts.map +1 -1
  24. package/dist/mcp-server/tools/definitions/brapi-dataframe-query.tool.d.ts +1 -1
  25. package/dist/mcp-server/tools/definitions/brapi-dataframe-query.tool.d.ts.map +1 -1
  26. package/dist/mcp-server/tools/definitions/brapi-describe-filters.tool.d.ts +1 -1
  27. package/dist/mcp-server/tools/definitions/brapi-describe-filters.tool.d.ts.map +1 -1
  28. package/dist/mcp-server/tools/definitions/brapi-export-genotype-matrix.tool.d.ts +88 -0
  29. package/dist/mcp-server/tools/definitions/brapi-export-genotype-matrix.tool.d.ts.map +1 -0
  30. package/dist/mcp-server/tools/definitions/brapi-export-genotype-matrix.tool.js +494 -0
  31. package/dist/mcp-server/tools/definitions/brapi-export-genotype-matrix.tool.js.map +1 -0
  32. package/dist/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.d.ts +7 -5
  33. package/dist/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.d.ts.map +1 -1
  34. package/dist/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.js +67 -120
  35. package/dist/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.js.map +1 -1
  36. package/dist/mcp-server/tools/definitions/brapi-find-germplasm.tool.d.ts +8 -6
  37. package/dist/mcp-server/tools/definitions/brapi-find-germplasm.tool.d.ts.map +1 -1
  38. package/dist/mcp-server/tools/definitions/brapi-find-germplasm.tool.js +54 -33
  39. package/dist/mcp-server/tools/definitions/brapi-find-germplasm.tool.js.map +1 -1
  40. package/dist/mcp-server/tools/definitions/brapi-find-images.tool.d.ts +8 -6
  41. package/dist/mcp-server/tools/definitions/brapi-find-images.tool.d.ts.map +1 -1
  42. package/dist/mcp-server/tools/definitions/brapi-find-images.tool.js +54 -33
  43. package/dist/mcp-server/tools/definitions/brapi-find-images.tool.js.map +1 -1
  44. package/dist/mcp-server/tools/definitions/brapi-find-locations.tool.d.ts +8 -6
  45. package/dist/mcp-server/tools/definitions/brapi-find-locations.tool.d.ts.map +1 -1
  46. package/dist/mcp-server/tools/definitions/brapi-find-locations.tool.js +62 -41
  47. package/dist/mcp-server/tools/definitions/brapi-find-locations.tool.js.map +1 -1
  48. package/dist/mcp-server/tools/definitions/brapi-find-observations.tool.d.ts +8 -6
  49. package/dist/mcp-server/tools/definitions/brapi-find-observations.tool.d.ts.map +1 -1
  50. package/dist/mcp-server/tools/definitions/brapi-find-observations.tool.js +54 -33
  51. package/dist/mcp-server/tools/definitions/brapi-find-observations.tool.js.map +1 -1
  52. package/dist/mcp-server/tools/definitions/brapi-find-studies.tool.d.ts +8 -6
  53. package/dist/mcp-server/tools/definitions/brapi-find-studies.tool.d.ts.map +1 -1
  54. package/dist/mcp-server/tools/definitions/brapi-find-studies.tool.js +52 -33
  55. package/dist/mcp-server/tools/definitions/brapi-find-studies.tool.js.map +1 -1
  56. package/dist/mcp-server/tools/definitions/brapi-find-variables.tool.d.ts +8 -6
  57. package/dist/mcp-server/tools/definitions/brapi-find-variables.tool.d.ts.map +1 -1
  58. package/dist/mcp-server/tools/definitions/brapi-find-variables.tool.js +54 -33
  59. package/dist/mcp-server/tools/definitions/brapi-find-variables.tool.js.map +1 -1
  60. package/dist/mcp-server/tools/definitions/brapi-find-variants.tool.d.ts +8 -6
  61. package/dist/mcp-server/tools/definitions/brapi-find-variants.tool.d.ts.map +1 -1
  62. package/dist/mcp-server/tools/definitions/brapi-find-variants.tool.js +54 -33
  63. package/dist/mcp-server/tools/definitions/brapi-find-variants.tool.js.map +1 -1
  64. package/dist/mcp-server/tools/definitions/brapi-germplasm-performance.tool.d.ts +60 -0
  65. package/dist/mcp-server/tools/definitions/brapi-germplasm-performance.tool.d.ts.map +1 -0
  66. package/dist/mcp-server/tools/definitions/brapi-germplasm-performance.tool.js +416 -0
  67. package/dist/mcp-server/tools/definitions/brapi-germplasm-performance.tool.js.map +1 -0
  68. package/dist/mcp-server/tools/definitions/brapi-get-germplasm.tool.d.ts +1 -1
  69. package/dist/mcp-server/tools/definitions/brapi-get-germplasm.tool.d.ts.map +1 -1
  70. package/dist/mcp-server/tools/definitions/brapi-get-image.tool.d.ts +1 -1
  71. package/dist/mcp-server/tools/definitions/brapi-get-image.tool.d.ts.map +1 -1
  72. package/dist/mcp-server/tools/definitions/brapi-get-study.tool.d.ts +1 -1
  73. package/dist/mcp-server/tools/definitions/brapi-get-study.tool.d.ts.map +1 -1
  74. package/dist/mcp-server/tools/definitions/brapi-raw-get.tool.d.ts +1 -1
  75. package/dist/mcp-server/tools/definitions/brapi-raw-get.tool.d.ts.map +1 -1
  76. package/dist/mcp-server/tools/definitions/brapi-raw-search.tool.d.ts +1 -1
  77. package/dist/mcp-server/tools/definitions/brapi-raw-search.tool.d.ts.map +1 -1
  78. package/dist/mcp-server/tools/definitions/brapi-server-info.tool.d.ts +1 -1
  79. package/dist/mcp-server/tools/definitions/brapi-server-info.tool.d.ts.map +1 -1
  80. package/dist/mcp-server/tools/definitions/brapi-submit-observations.tool.d.ts +1 -1
  81. package/dist/mcp-server/tools/definitions/brapi-submit-observations.tool.d.ts.map +1 -1
  82. package/dist/mcp-server/tools/definitions/brapi-walk-pedigree.tool.d.ts +1 -1
  83. package/dist/mcp-server/tools/definitions/brapi-walk-pedigree.tool.d.ts.map +1 -1
  84. package/dist/mcp-server/tools/definitions/index.d.ts +225 -61
  85. package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -1
  86. package/dist/mcp-server/tools/definitions/index.js +6 -0
  87. package/dist/mcp-server/tools/definitions/index.js.map +1 -1
  88. package/dist/mcp-server/tools/shared/canvas-columns.d.ts +32 -0
  89. package/dist/mcp-server/tools/shared/canvas-columns.d.ts.map +1 -0
  90. package/dist/mcp-server/tools/shared/canvas-columns.js +98 -0
  91. package/dist/mcp-server/tools/shared/canvas-columns.js.map +1 -0
  92. package/dist/mcp-server/tools/shared/find-helpers.d.ts +1 -1
  93. package/dist/mcp-server/tools/shared/find-helpers.d.ts.map +1 -1
  94. package/dist/mcp-server/tools/shared/find-helpers.js +6 -2
  95. package/dist/mcp-server/tools/shared/find-helpers.js.map +1 -1
  96. package/dist/mcp-server/tools/shared/genotype-calls.d.ts +81 -0
  97. package/dist/mcp-server/tools/shared/genotype-calls.d.ts.map +1 -0
  98. package/dist/mcp-server/tools/shared/genotype-calls.js +172 -0
  99. package/dist/mcp-server/tools/shared/genotype-calls.js.map +1 -0
  100. package/dist/mcp-server/tools/shared/observations.d.ts +87 -0
  101. package/dist/mcp-server/tools/shared/observations.d.ts.map +1 -0
  102. package/dist/mcp-server/tools/shared/observations.js +285 -0
  103. package/dist/mcp-server/tools/shared/observations.js.map +1 -0
  104. package/manifest.json +1 -1
  105. package/package.json +6 -5
  106. package/server.json +3 -3
@@ -0,0 +1,366 @@
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 { tool, z } from '@cyanheads/mcp-ts-core';
20
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
21
+ import { getServerConfig } from '../../../config/server-config.js';
22
+ import { getBrapiClient } from '../../../services/brapi-client/index.js';
23
+ import { resolveDialect } from '../../../services/brapi-dialect/index.js';
24
+ import { getCanvasBridge } from '../../../services/canvas-bridge/index.js';
25
+ import { getCapabilityRegistry } from '../../../services/capability-registry/index.js';
26
+ import { buildUniqueColumns } from '../shared/canvas-columns.js';
27
+ import { AliasInput, DataframeHandleSchema, ExtraFiltersInput, LoadLimitInput, renderDataframeHandle, requireRegisteredConnection, } from '../shared/find-helpers.js';
28
+ import { pullStudyObservations } from '../shared/observations.js';
29
+ // ---------------------------------------------------------------------------
30
+ // Output schema
31
+ // ---------------------------------------------------------------------------
32
+ const OutputSchema = z.object({
33
+ alias: z.string().describe('Alias of the registered BrAPI connection the call used.'),
34
+ studies: z.array(z.string()).describe('studyDbIds that were queried to build the matrix.'),
35
+ shape: z
36
+ .enum(['wide', 'long'])
37
+ .describe('Matrix shape — wide (one row per germplasm, one column per variable) or long (one row per observation).'),
38
+ aggregate: z
39
+ .enum(['mean', 'median', 'first', 'all'])
40
+ .describe('Aggregation applied to replicate observations (wide shape only). `all` keeps one row per replicate.'),
41
+ observationCount: z
42
+ .number()
43
+ .int()
44
+ .nonnegative()
45
+ .describe('Total raw observations collected before pivoting.'),
46
+ germplasmCount: z
47
+ .number()
48
+ .int()
49
+ .nonnegative()
50
+ .describe('Number of distinct germplasm in the matrix.'),
51
+ variableCount: z
52
+ .number()
53
+ .int()
54
+ .nonnegative()
55
+ .describe('Number of distinct observation variables in the matrix.'),
56
+ variableLegend: z
57
+ .record(z.string(), z.string())
58
+ .describe('Mapping of safe column identifier → observationVariableName. Wide-matrix column names are SQL-safe identifiers derived from observationVariableDbId (sanitized for DuckDB); consult this map to resolve a column back to its variable display name.'),
59
+ dataframe: DataframeHandleSchema.optional().describe('Canvas dataframe handle for the materialized matrix. Omitted when no observations were found. Query with brapi_dataframe_query (SQL). Long-form columns: germplasmDbId, observationVariableDbId, studyDbId, value, replicateIndex. Wide-form columns: germplasmDbId, germplasmName, one column per variable (SQL-safe identifier derived from observationVariableDbId — see variableLegend).'),
60
+ warnings: z
61
+ .array(z.string())
62
+ .describe('Advisory messages (empty studies, non-numeric aggregation skips, fallback paths).'),
63
+ });
64
+ // ---------------------------------------------------------------------------
65
+ // Tool definition
66
+ // ---------------------------------------------------------------------------
67
+ export const brapiBuildPhenotypeMatrix = tool('brapi_build_phenotype_matrix', {
68
+ description: 'Pull observations across one or more studies and pivot them into a germplasm × trait matrix materialized as a canvas dataframe. Returns a dataframe handle (query with brapi_dataframe_query) plus a summary of dimensions and aggregate method. Long-form output is suitable for downstream GROUP BY analysis by study, germplasm, or variable.',
69
+ annotations: { readOnlyHint: true, openWorldHint: true },
70
+ errors: [
71
+ {
72
+ reason: 'unknown_alias',
73
+ code: JsonRpcErrorCode.NotFound,
74
+ when: 'No connection has been registered under the requested alias',
75
+ recovery: 'Run brapi_connect with this alias (or omit `alias` to use the default connection) before calling brapi_build_phenotype_matrix.',
76
+ },
77
+ {
78
+ reason: 'all_filters_dropped',
79
+ code: JsonRpcErrorCode.ValidationError,
80
+ when: 'The active dialect dropped every filter supplied — the call would silently widen to the unfiltered baseline',
81
+ recovery: 'Drop unsupported filters or use studies / germplasm / variables to scope the query to supported filter paths on the active dialect.',
82
+ },
83
+ {
84
+ reason: 'no_observation_path',
85
+ code: JsonRpcErrorCode.ServiceUnavailable,
86
+ when: 'Neither /observations nor /observationunits returned data for any requested study after probing both paths',
87
+ recovery: 'Verify the studyDbIds exist and the BrAPI server exposes /observations or /observationunits. Use brapi_server_info to inspect the capability list.',
88
+ },
89
+ ],
90
+ input: z.object({
91
+ alias: AliasInput,
92
+ studies: z
93
+ .array(z.string())
94
+ .min(1)
95
+ .describe('studyDbIds to include in the matrix. At least one is required — the tool is study-anchored to avoid full-table scans.'),
96
+ variables: z
97
+ .array(z.string())
98
+ .optional()
99
+ .describe('Optional subset of observationVariableDbIds to include. Omit to include all variables found in the queried studies.'),
100
+ germplasm: z
101
+ .array(z.string())
102
+ .optional()
103
+ .describe('Optional subset of germplasmDbIds to include. Omit to include all germplasm found in the queried studies.'),
104
+ shape: z
105
+ .enum(['wide', 'long'])
106
+ .default('wide')
107
+ .describe('Matrix shape. `wide` — one row per germplasm, one column per variable, cell = aggregated value. `long` — one row per observation with columns: germplasmDbId, observationVariableDbId, studyDbId, value, replicateIndex. When `aggregate:"all"` is combined with `shape:"wide"`, the output falls back to long form with a replicateIndex column.'),
108
+ aggregate: z
109
+ .enum(['mean', 'median', 'first', 'all'])
110
+ .default('mean')
111
+ .describe('How to aggregate replicate observations (multiple readings of the same variable on the same germplasm). `mean` and `median` attempt numeric conversion and skip non-numeric values (e.g. categorical traits). `first` keeps the first value seen. `all` keeps every replicate as a separate row (produces long-form output even when shape is "wide"). Default: `mean`.'),
112
+ loadLimit: LoadLimitInput,
113
+ extraFilters: ExtraFiltersInput,
114
+ }),
115
+ output: OutputSchema,
116
+ async handler(input, ctx) {
117
+ const client = getBrapiClient();
118
+ const bridge = getCanvasBridge();
119
+ const config = getServerConfig();
120
+ const capabilities = getCapabilityRegistry();
121
+ const connection = await requireRegisteredConnection(ctx, input.alias);
122
+ const capabilityLookup = connection.resolvedAuth ? { auth: connection.resolvedAuth } : {};
123
+ const profile = await capabilities.profile(connection.baseUrl, ctx, capabilityLookup);
124
+ const dialect = await resolveDialect(connection, ctx, capabilityLookup);
125
+ const loadLimit = input.loadLimit ?? config.loadLimit;
126
+ const warnings = [];
127
+ const allObs = [];
128
+ // Collect observations study-by-study. Isolation per study avoids
129
+ // unbounded queries and preserves studyDbId on each row.
130
+ for (const studyDbId of input.studies) {
131
+ const studyObs = await pullStudyObservations({
132
+ studyDbId,
133
+ input,
134
+ client,
135
+ connection,
136
+ profile: profile.supported,
137
+ dialect,
138
+ config,
139
+ loadLimit,
140
+ warnings,
141
+ ctx,
142
+ });
143
+ if (studyObs === null) {
144
+ throw ctx.fail('no_observation_path', `Neither /observations nor /observationunits returned a usable path for study '${studyDbId}'. Check brapi_server_info for the capability list.`, { ...ctx.recoveryFor('no_observation_path'), studyDbId });
145
+ }
146
+ allObs.push(...studyObs);
147
+ }
148
+ // Apply variable and germplasm filters if requested
149
+ const filteredObs = filterObservations(allObs, input.variables, input.germplasm);
150
+ if (filteredObs.length === 0) {
151
+ warnings.push('No observations matched after collecting from the requested studies. The matrix will be empty.');
152
+ }
153
+ // Build variable column plan: distinct variables in encounter order →
154
+ // SQL-safe column names, plus a legend mapping safe column → display name.
155
+ const varOrder = [];
156
+ const varDisplay = new Map();
157
+ for (const o of filteredObs) {
158
+ if (!varDisplay.has(o.observationVariableDbId)) {
159
+ varDisplay.set(o.observationVariableDbId, o.observationVariableName);
160
+ varOrder.push(o.observationVariableDbId);
161
+ }
162
+ }
163
+ const { columns: variableColumns, toOriginal: columnToVariable } = buildUniqueColumns(varOrder);
164
+ const variableLegend = {};
165
+ for (const col of variableColumns) {
166
+ const varId = columnToVariable[col];
167
+ if (varId !== undefined)
168
+ variableLegend[col] = varDisplay.get(varId) ?? varId;
169
+ }
170
+ // Determine effective shape — `all` replicates force long form
171
+ const effectiveShape = input.shape === 'wide' && input.aggregate === 'all' ? 'long' : input.shape;
172
+ if (input.shape === 'wide' && input.aggregate === 'all') {
173
+ warnings.push('`shape:"wide"` combined with `aggregate:"all"` produces long-form output with a replicateIndex column (no pivot possible when all replicates are kept).');
174
+ }
175
+ // Build the matrix rows
176
+ let matrixRows;
177
+ if (effectiveShape === 'long') {
178
+ matrixRows = buildLongRows(filteredObs);
179
+ }
180
+ else {
181
+ matrixRows = buildWideRows(filteredObs, input.aggregate, variableColumns, columnToVariable, warnings);
182
+ }
183
+ // Distinct germplasm count (from filteredObs, not matrixRows)
184
+ const germplasmSet = new Set(filteredObs.map((o) => o.germplasmDbId));
185
+ const result = {
186
+ alias: connection.alias,
187
+ studies: input.studies,
188
+ shape: input.shape,
189
+ aggregate: input.aggregate,
190
+ observationCount: filteredObs.length,
191
+ germplasmCount: germplasmSet.size,
192
+ variableCount: varOrder.length,
193
+ variableLegend,
194
+ warnings,
195
+ };
196
+ // Only materialize when there are actual rows — DuckDB rejects an empty
197
+ // schema (no columns), and an empty dataframe handle is misleading.
198
+ if (matrixRows.length > 0) {
199
+ const dataframe = await bridge.registerDataframe(ctx, {
200
+ source: 'build_phenotype_matrix',
201
+ baseUrl: connection.baseUrl,
202
+ query: {
203
+ studies: input.studies,
204
+ variables: input.variables,
205
+ germplasm: input.germplasm,
206
+ shape: input.shape,
207
+ aggregate: input.aggregate,
208
+ },
209
+ rows: matrixRows,
210
+ });
211
+ result.dataframe = {
212
+ tableName: dataframe.tableName,
213
+ rowCount: dataframe.rowCount,
214
+ columns: dataframe.columns,
215
+ createdAt: dataframe.createdAt,
216
+ expiresAt: dataframe.expiresAt,
217
+ };
218
+ }
219
+ return result;
220
+ },
221
+ format: (result) => {
222
+ const lines = [];
223
+ lines.push(`# Phenotype matrix — ${result.germplasmCount} germplasm × ${result.variableCount} variables — \`${result.alias}\``);
224
+ lines.push('');
225
+ lines.push(`Shape: **${result.shape}** · Aggregate: **${result.aggregate}** · Observations collected: ${result.observationCount}`);
226
+ lines.push(`Studies queried: ${result.studies.join(', ')}`);
227
+ lines.push('');
228
+ // Variable legend
229
+ const legendEntries = Object.entries(result.variableLegend);
230
+ if (legendEntries.length > 0) {
231
+ lines.push('## Variable legend');
232
+ for (const [col, name] of legendEntries) {
233
+ lines.push(`- \`${col}\` → ${name}`);
234
+ }
235
+ lines.push('');
236
+ }
237
+ // Dataframe handle
238
+ if (result.dataframe) {
239
+ lines.push('## Dataframe handle');
240
+ lines.push(...renderDataframeHandle(result.dataframe));
241
+ lines.push('');
242
+ }
243
+ else {
244
+ lines.push('_No observations found — dataframe not materialized._');
245
+ lines.push('');
246
+ }
247
+ if (result.warnings.length > 0) {
248
+ lines.push('## Warnings');
249
+ for (const w of result.warnings) {
250
+ lines.push(`- ${w}`);
251
+ }
252
+ }
253
+ return [{ type: 'text', text: lines.join('\n') }];
254
+ },
255
+ });
256
+ // ---------------------------------------------------------------------------
257
+ // Filter helpers
258
+ // ---------------------------------------------------------------------------
259
+ function filterObservations(obs, variables, germplasm) {
260
+ let result = obs;
261
+ if (variables?.length) {
262
+ const set = new Set(variables);
263
+ result = result.filter((o) => set.has(o.observationVariableDbId));
264
+ }
265
+ if (germplasm?.length) {
266
+ const set = new Set(germplasm);
267
+ result = result.filter((o) => set.has(o.germplasmDbId));
268
+ }
269
+ return result;
270
+ }
271
+ // ---------------------------------------------------------------------------
272
+ // Long-form row builder
273
+ // ---------------------------------------------------------------------------
274
+ function buildLongRows(obs) {
275
+ // Group by (germplasmDbId, observationVariableDbId, studyDbId) to assign replicate index
276
+ const replicateCounts = new Map();
277
+ return obs.map((o) => {
278
+ const key = `${o.germplasmDbId}|${o.observationVariableDbId}|${o.studyDbId}`;
279
+ const idx = replicateCounts.get(key) ?? 0;
280
+ replicateCounts.set(key, idx + 1);
281
+ return {
282
+ germplasmDbId: o.germplasmDbId,
283
+ observationVariableDbId: o.observationVariableDbId,
284
+ studyDbId: o.studyDbId,
285
+ value: o.value,
286
+ replicateIndex: idx,
287
+ };
288
+ });
289
+ }
290
+ // ---------------------------------------------------------------------------
291
+ // Wide-form row builder
292
+ // ---------------------------------------------------------------------------
293
+ function buildWideRows(obs, aggregate, variableColumns, columnToVariable, warnings) {
294
+ if (aggregate === 'all') {
295
+ // Caller already redirected to long for 'all' + 'wide' — this branch should
296
+ // not be reached, but guard defensively.
297
+ return buildLongRows(obs);
298
+ }
299
+ // Group observations: germplasmDbId → variableDbId → values[]
300
+ const groups = new Map();
301
+ // Collect germplasm names (first observation per germplasm)
302
+ const germplasmNames = new Map();
303
+ for (const o of obs) {
304
+ if (!germplasmNames.has(o.germplasmDbId)) {
305
+ germplasmNames.set(o.germplasmDbId, o.germplasmName);
306
+ }
307
+ let byVar = groups.get(o.germplasmDbId);
308
+ if (!byVar) {
309
+ byVar = new Map();
310
+ groups.set(o.germplasmDbId, byVar);
311
+ }
312
+ const vals = byVar.get(o.observationVariableDbId) ?? [];
313
+ vals.push(o.value);
314
+ byVar.set(o.observationVariableDbId, vals);
315
+ }
316
+ const nonNumericWarned = new Set();
317
+ const rows = [];
318
+ for (const [germplasmDbId, byVar] of groups) {
319
+ const row = {
320
+ germplasmDbId,
321
+ germplasmName: germplasmNames.get(germplasmDbId) ?? germplasmDbId,
322
+ };
323
+ for (const col of variableColumns) {
324
+ const varId = columnToVariable[col];
325
+ const vals = varId ? byVar.get(varId) : undefined;
326
+ if (!vals || vals.length === 0) {
327
+ row[col] = null;
328
+ continue;
329
+ }
330
+ row[col] = aggregateValues(vals, aggregate, varId, nonNumericWarned, warnings);
331
+ }
332
+ rows.push(row);
333
+ }
334
+ return rows;
335
+ }
336
+ // ---------------------------------------------------------------------------
337
+ // Aggregation
338
+ // ---------------------------------------------------------------------------
339
+ function aggregateValues(values, aggregate, varId, nonNumericWarned, warnings) {
340
+ if (aggregate === 'first') {
341
+ return values[0] ?? null;
342
+ }
343
+ // numeric aggregation
344
+ const nums = values.map((v) => Number(v)).filter((n) => !Number.isNaN(n));
345
+ if (nums.length === 0) {
346
+ if (!nonNumericWarned.has(varId)) {
347
+ nonNumericWarned.add(varId);
348
+ warnings.push(`Variable '${varId}': all values are non-numeric — cannot compute ${aggregate}. Cell set to null. Use aggregate:"first" or "all" for categorical traits.`);
349
+ }
350
+ return null;
351
+ }
352
+ if (aggregate === 'mean') {
353
+ return nums.reduce((a, b) => a + b, 0) / nums.length;
354
+ }
355
+ // median (nums is non-empty here — guarded above)
356
+ const sorted = [...nums].sort((a, b) => a - b);
357
+ const mid = Math.floor(sorted.length / 2);
358
+ const hi = sorted[mid];
359
+ if (hi === undefined)
360
+ return null;
361
+ if (sorted.length % 2 !== 0)
362
+ return hi;
363
+ const lo = sorted[mid - 1];
364
+ return lo === undefined ? hi : (lo + hi) / 2;
365
+ }
366
+ //# sourceMappingURL=brapi-build-phenotype-matrix.tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brapi-build-phenotype-matrix.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/brapi-build-phenotype-matrix.tool.ts"],"names":[],"mappings":"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"}
@@ -99,5 +99,5 @@ export declare const brapiConnect: import("@cyanheads/mcp-ts-core").ToolDefiniti
99
99
  readonly code: JsonRpcErrorCode.Forbidden;
100
100
  readonly when: "Token endpoint responded but did not return an access_token";
101
101
  readonly recovery: "Confirm the credentials are valid and the upstream IdP issues access tokens for this grant.";
102
- }]>;
102
+ }], undefined>;
103
103
  //# sourceMappingURL=brapi-connect.tool.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"brapi-connect.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/brapi-connect.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAqBjE,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyFvB,CAAC"}
1
+ {"version":3,"file":"brapi-connect.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/brapi-connect.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAqBjE,eAAO,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAyFvB,CAAC"}
@@ -38,5 +38,5 @@ export declare const brapiDataframeDescribe: import("@cyanheads/mcp-ts-core").To
38
38
  readonly code: JsonRpcErrorCode.Forbidden;
39
39
  readonly when: "This server is running as a shared HTTP endpoint without per-caller auth — listing every dataframe would expose other concurrent clients' workspaces, since all callers resolve to one shared tenant.";
40
40
  readonly recovery: "Pass `dataframe` with a specific name — either from a prior find_* spillover result (`result.dataframe.tableName`) or one you registered via `brapi_dataframe_query` with `registerAs`. Listing all dataframes is not available on this deployment.";
41
- }]>;
41
+ }], undefined>;
42
42
  //# sourceMappingURL=brapi-dataframe-describe.tool.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"brapi-dataframe-describe.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/brapi-dataframe-describe.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAEjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AA6CjE,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;GAkCjC,CAAC"}
1
+ {"version":3,"file":"brapi-dataframe-describe.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/brapi-dataframe-describe.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAEjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AA6CjE,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;cAkCjC,CAAC"}
@@ -15,5 +15,5 @@ export declare const brapiDataframeDrop: import("@cyanheads/mcp-ts-core").ToolDe
15
15
  }, z.core.$strip>, z.ZodObject<{
16
16
  dataframe: z.ZodString;
17
17
  dropped: z.ZodBoolean;
18
- }, z.core.$strip>, undefined>;
18
+ }, z.core.$strip>, undefined, undefined>;
19
19
  //# sourceMappingURL=brapi-dataframe-drop.tool.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"brapi-dataframe-drop.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/brapi-dataframe-drop.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAmBjD,eAAO,MAAM,kBAAkB;;;;;6BAqB7B,CAAC"}
1
+ {"version":3,"file":"brapi-dataframe-drop.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/brapi-dataframe-drop.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAmBjD,eAAO,MAAM,kBAAkB;;;;;wCAqB7B,CAAC"}
@@ -65,5 +65,5 @@ export declare const brapiDataframeExport: import("@cyanheads/mcp-ts-core").Tool
65
65
  readonly code: JsonRpcErrorCode.ValidationError;
66
66
  readonly when: "Both `columns` and `sql` were supplied";
67
67
  readonly recovery: "Pass either `columns` for a thin projection or `sql` for filtering/aggregation, not both.";
68
- }]>;
68
+ }], undefined>;
69
69
  //# sourceMappingURL=brapi-dataframe-export.tool.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"brapi-dataframe-export.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/brapi-dataframe-export.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,EAAsB,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAE/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAoEjE,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkH/B,CAAC"}
1
+ {"version":3,"file":"brapi-dataframe-export.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/brapi-dataframe-export.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,OAAO,EAAsB,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAE/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAoEjE,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAkH/B,CAAC"}
@@ -42,5 +42,5 @@ export declare const brapiDataframeQuery: import("@cyanheads/mcp-ts-core").ToolD
42
42
  readonly code: JsonRpcErrorCode.ValidationError;
43
43
  readonly when: "SQL violated read-only rules (multi-statement, non-SELECT, or disallowed operation)";
44
44
  readonly recovery: "Submit a single SELECT statement using only registered dataframes. For changes, use `registerAs` in this tool to materialize a result, or brapi_dataframe_drop to remove a dataframe.";
45
- }]>;
45
+ }], undefined>;
46
46
  //# sourceMappingURL=brapi-dataframe-query.tool.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"brapi-dataframe-query.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/brapi-dataframe-query.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAsB,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAO/D,OAAO,EAAE,gBAAgB,EAAY,MAAM,+BAA+B,CAAC;AAmH3E,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;GAmE9B,CAAC"}
1
+ {"version":3,"file":"brapi-dataframe-query.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/brapi-dataframe-query.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,EAAsB,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAO/D,OAAO,EAAE,gBAAgB,EAAY,MAAM,+BAA+B,CAAC;AAmH3E,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;cAmE9B,CAAC"}
@@ -37,5 +37,5 @@ export declare const brapiDescribeFilters: import("@cyanheads/mcp-ts-core").Tool
37
37
  readonly code: JsonRpcErrorCode.NotFound;
38
38
  readonly when: "No filter catalog is registered for the requested endpoint";
39
39
  readonly recovery: "Pick an endpoint from data.availableEndpoints — same set as the input enum (studies, germplasm, observations, variables, images, variants, locations).";
40
- }]>;
40
+ }], undefined>;
41
41
  //# sourceMappingURL=brapi-describe-filters.tool.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"brapi-describe-filters.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/brapi-describe-filters.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAgBjE,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2E/B,CAAC"}
1
+ {"version":3,"file":"brapi-describe-filters.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/brapi-describe-filters.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAgBjE,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA2E/B,CAAC"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * @fileoverview `brapi_export_genotype_matrix` — pull genotype calls for a
3
+ * germplasm × variant set and pivot them into a matrix in the requested format.
4
+ *
5
+ * Three output formats:
6
+ *
7
+ * - `matrix-json`: Wide germplasm × variant table registered as a canvas
8
+ * dataframe (`df_<uuid>`). One row per call-set (germplasm); one column per
9
+ * variant. Column names are sanitized for DuckDB (SQL-safe identifiers); a
10
+ * `variantColumnLegend` maps sanitized name → original variant ID.
11
+ *
12
+ * - `vcf-lite`: Standard VCF-subset text (`#CHROM POS ID REF ALT <sample…>`),
13
+ * one row per variant, returned in the `vcf` output field. CHROM/POS/REF/ALT
14
+ * come from a `/variants` metadata pull; `.` when the server doesn't provide
15
+ * them (common — the BrAPI test server leaves them null). The wide matrix is
16
+ * also registered as a dataframe for SQL follow-up.
17
+ *
18
+ * - `plink`: `.ped` and `.map` text returned in the `ped` / `map` output fields.
19
+ * `.map` carries chromosome + base-pair position from the variant pull; `.ped`
20
+ * carries biallelic genotype pairs split from each call's genotype string.
21
+ * Alleles are passed through verbatim (numeric 0/1 codings are not recoded to
22
+ * nucleotides). The wide matrix is also registered as a dataframe.
23
+ *
24
+ * The genotype-call pull infrastructure is shared with `brapi_find_genotype_calls`
25
+ * via `src/mcp-server/tools/shared/genotype-calls.ts`; column sanitization is
26
+ * shared via `src/mcp-server/tools/shared/canvas-columns.ts`.
27
+ *
28
+ * @module mcp-server/tools/definitions/brapi-export-genotype-matrix.tool
29
+ */
30
+ import { z } from '@cyanheads/mcp-ts-core';
31
+ import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
32
+ export declare const brapiExportGenotypeMatrix: import("@cyanheads/mcp-ts-core").ToolDefinition<z.ZodObject<{
33
+ alias: z.ZodOptional<z.ZodString>;
34
+ germplasmDbIds: z.ZodOptional<z.ZodArray<z.ZodString>>;
35
+ variantSetDbId: z.ZodString;
36
+ format: z.ZodEnum<{
37
+ plink: "plink";
38
+ "vcf-lite": "vcf-lite";
39
+ "matrix-json": "matrix-json";
40
+ }>;
41
+ maxCalls: z.ZodOptional<z.ZodNumber>;
42
+ }, z.core.$strip>, z.ZodObject<{
43
+ alias: z.ZodString;
44
+ format: z.ZodEnum<{
45
+ plink: "plink";
46
+ "vcf-lite": "vcf-lite";
47
+ "matrix-json": "matrix-json";
48
+ }>;
49
+ rowCount: z.ZodNumber;
50
+ columnCount: z.ZodNumber;
51
+ variantColumnLegend: z.ZodRecord<z.ZodString, z.ZodString>;
52
+ callFormatting: z.ZodObject<{
53
+ expandHomozygotes: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
54
+ unknownString: z.ZodOptional<z.ZodNullable<z.ZodString>>;
55
+ sepPhased: z.ZodOptional<z.ZodNullable<z.ZodString>>;
56
+ sepUnphased: z.ZodOptional<z.ZodNullable<z.ZodString>>;
57
+ }, z.core.$strip>;
58
+ dataframe: z.ZodObject<{
59
+ tableName: z.ZodString;
60
+ rowCount: z.ZodNumber;
61
+ columns: z.ZodArray<z.ZodString>;
62
+ createdAt: z.ZodString;
63
+ expiresAt: z.ZodString;
64
+ truncated: z.ZodOptional<z.ZodBoolean>;
65
+ maxRows: z.ZodOptional<z.ZodNumber>;
66
+ }, z.core.$strip>;
67
+ vcf: z.ZodOptional<z.ZodString>;
68
+ ped: z.ZodOptional<z.ZodString>;
69
+ map: z.ZodOptional<z.ZodString>;
70
+ truncated: z.ZodBoolean;
71
+ warnings: z.ZodArray<z.ZodString>;
72
+ }, z.core.$strip>, readonly [{
73
+ readonly reason: "unknown_alias";
74
+ readonly code: JsonRpcErrorCode.NotFound;
75
+ readonly when: "No connection has been registered under the requested alias";
76
+ readonly recovery: "Run brapi_connect with this alias (or omit `alias` to use the default connection) before calling brapi_export_genotype_matrix.";
77
+ }, {
78
+ readonly reason: "no_filters";
79
+ readonly code: JsonRpcErrorCode.ValidationError;
80
+ readonly when: "No variantSetDbId was provided";
81
+ readonly recovery: "Provide variantSetDbId before retrying — unfiltered genotype-call pulls are too expensive.";
82
+ }, {
83
+ readonly reason: "search_endpoint_disabled";
84
+ readonly code: JsonRpcErrorCode.ValidationError;
85
+ readonly when: "The active dialect declares POST /search/calls as known-dead on this server";
86
+ readonly recovery: "Connect to a different BrAPI server that exposes a working /search/calls route — genotype-call workflows are not viable here.";
87
+ }], undefined>;
88
+ //# sourceMappingURL=brapi-export-genotype-matrix.tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"brapi-export-genotype-matrix.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/brapi-export-genotype-matrix.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAGH,OAAO,EAAQ,CAAC,EAAE,MAAM,wBAAwB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AA2GjE,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cAyNpC,CAAC"}