@cyanheads/brapi-mcp-server 0.4.14 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +23 -19
- package/README.md +40 -26
- package/changelog/0.5.x/0.5.0.md +59 -0
- package/dist/config/builtin-aliases.d.ts +1 -1
- package/dist/config/builtin-aliases.js +1 -1
- package/dist/config/server-config.d.ts +3 -3
- package/dist/config/server-config.d.ts.map +1 -1
- package/dist/config/server-config.js +13 -13
- package/dist/config/server-config.js.map +1 -1
- package/dist/index.js +62 -15
- package/dist/index.js.map +1 -1
- package/dist/mcp-server/prompts/definitions/brapi-eda-study.prompt.js +1 -1
- package/dist/mcp-server/prompts/definitions/brapi-eda-study.prompt.js.map +1 -1
- package/dist/mcp-server/prompts/definitions/brapi-meta-analysis.prompt.js +3 -3
- package/dist/mcp-server/prompts/definitions/brapi-meta-analysis.prompt.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-dataframe-describe.tool.d.ts +8 -11
- package/dist/mcp-server/tools/definitions/brapi-dataframe-describe.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-dataframe-describe.tool.js +15 -25
- 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 +6 -10
- package/dist/mcp-server/tools/definitions/brapi-dataframe-drop.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-dataframe-drop.tool.js +6 -16
- package/dist/mcp-server/tools/definitions/brapi-dataframe-drop.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-dataframe-export.tool.d.ts +69 -0
- package/dist/mcp-server/tools/definitions/brapi-dataframe-export.tool.d.ts.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-dataframe-export.tool.js +233 -0
- package/dist/mcp-server/tools/definitions/brapi-dataframe-export.tool.js.map +1 -0
- package/dist/mcp-server/tools/definitions/brapi-dataframe-query.tool.d.ts +19 -11
- 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 +80 -28
- 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 +4 -6
- package/dist/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.js +28 -36
- package/dist/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-germplasm.tool.d.ts +3 -5
- package/dist/mcp-server/tools/definitions/brapi-find-germplasm.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-germplasm.tool.js +19 -19
- package/dist/mcp-server/tools/definitions/brapi-find-germplasm.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-images.tool.d.ts +4 -6
- package/dist/mcp-server/tools/definitions/brapi-find-images.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-images.tool.js +16 -16
- package/dist/mcp-server/tools/definitions/brapi-find-images.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-locations.tool.d.ts +3 -5
- package/dist/mcp-server/tools/definitions/brapi-find-locations.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-locations.tool.js +15 -15
- package/dist/mcp-server/tools/definitions/brapi-find-locations.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-observations.tool.d.ts +4 -6
- package/dist/mcp-server/tools/definitions/brapi-find-observations.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-observations.tool.js +17 -17
- package/dist/mcp-server/tools/definitions/brapi-find-observations.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-studies.tool.d.ts +4 -6
- package/dist/mcp-server/tools/definitions/brapi-find-studies.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-studies.tool.js +17 -17
- package/dist/mcp-server/tools/definitions/brapi-find-studies.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-variables.tool.d.ts +2 -4
- package/dist/mcp-server/tools/definitions/brapi-find-variables.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-variables.tool.js +17 -17
- package/dist/mcp-server/tools/definitions/brapi-find-variables.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-variants.tool.d.ts +3 -5
- package/dist/mcp-server/tools/definitions/brapi-find-variants.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-find-variants.tool.js +15 -15
- package/dist/mcp-server/tools/definitions/brapi-find-variants.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-raw-get.tool.d.ts +17 -2
- package/dist/mcp-server/tools/definitions/brapi-raw-get.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-raw-get.tool.js +51 -7
- package/dist/mcp-server/tools/definitions/brapi-raw-get.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-raw-search.tool.d.ts +16 -2
- package/dist/mcp-server/tools/definitions/brapi-raw-search.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-raw-search.tool.js +51 -5
- package/dist/mcp-server/tools/definitions/brapi-raw-search.tool.js.map +1 -1
- package/dist/mcp-server/tools/definitions/index.d.ts +141 -165
- package/dist/mcp-server/tools/definitions/index.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/index.js +28 -17
- package/dist/mcp-server/tools/definitions/index.js.map +1 -1
- package/dist/mcp-server/tools/shared/find-helpers.d.ts +52 -41
- package/dist/mcp-server/tools/shared/find-helpers.d.ts.map +1 -1
- package/dist/mcp-server/tools/shared/find-helpers.js +89 -66
- package/dist/mcp-server/tools/shared/find-helpers.js.map +1 -1
- package/dist/mcp-server/tools/shared/raw-routing-hints.d.ts.map +1 -1
- package/dist/mcp-server/tools/shared/raw-routing-hints.js +6 -6
- package/dist/mcp-server/tools/shared/raw-routing-hints.js.map +1 -1
- package/dist/services/canvas-bridge/canvas-bridge.d.ts +69 -44
- package/dist/services/canvas-bridge/canvas-bridge.d.ts.map +1 -1
- package/dist/services/canvas-bridge/canvas-bridge.js +143 -112
- package/dist/services/canvas-bridge/canvas-bridge.js.map +1 -1
- package/dist/services/canvas-bridge/index.d.ts +1 -1
- package/dist/services/canvas-bridge/index.d.ts.map +1 -1
- package/dist/services/canvas-bridge/index.js +1 -1
- package/dist/services/canvas-bridge/index.js.map +1 -1
- package/dist/services/canvas-bridge/types.d.ts +11 -12
- package/dist/services/canvas-bridge/types.d.ts.map +1 -1
- package/dist/services/canvas-bridge/types.js +4 -4
- package/package.json +3 -11
- package/server.json +3 -3
- package/dist/mcp-server/resources/definitions/brapi-dataset.resource.d.ts +0 -13
- package/dist/mcp-server/resources/definitions/brapi-dataset.resource.d.ts.map +0 -1
- package/dist/mcp-server/resources/definitions/brapi-dataset.resource.js +0 -26
- package/dist/mcp-server/resources/definitions/brapi-dataset.resource.js.map +0 -1
- package/dist/mcp-server/tools/definitions/brapi-manage-dataset.tool.d.ts +0 -89
- package/dist/mcp-server/tools/definitions/brapi-manage-dataset.tool.d.ts.map +0 -1
- package/dist/mcp-server/tools/definitions/brapi-manage-dataset.tool.js +0 -306
- package/dist/mcp-server/tools/definitions/brapi-manage-dataset.tool.js.map +0 -1
- package/dist/services/dataset-store/dataset-store.d.ts +0 -44
- package/dist/services/dataset-store/dataset-store.d.ts.map +0 -1
- package/dist/services/dataset-store/dataset-store.js +0 -208
- package/dist/services/dataset-store/dataset-store.js.map +0 -1
- package/dist/services/dataset-store/index.d.ts +0 -8
- package/dist/services/dataset-store/index.d.ts.map +0 -1
- package/dist/services/dataset-store/index.js +0 -7
- package/dist/services/dataset-store/index.js.map +0 -1
- package/dist/services/dataset-store/types.d.ts +0 -72
- package/dist/services/dataset-store/types.d.ts.map +0 -1
- package/dist/services/dataset-store/types.js +0 -8
- package/dist/services/dataset-store/types.js.map +0 -1
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* @fileoverview Shared building blocks for `find_*` tools — Zod fragments for
|
|
3
3
|
* common inputs (alias, loadLimit, extraFilters), utilities to merge named
|
|
4
4
|
* filters with the passthrough map, a generic distribution aggregator, and
|
|
5
|
-
* the
|
|
6
|
-
*
|
|
5
|
+
* the spillover handler that turns a "too many rows" result into a canvas
|
|
6
|
+
* dataframe handle.
|
|
7
7
|
*
|
|
8
8
|
* @module mcp-server/tools/shared/find-helpers
|
|
9
9
|
*/
|
|
@@ -11,14 +11,14 @@ import { type Context, type HandlerContext, z } from '@cyanheads/mcp-ts-core';
|
|
|
11
11
|
import type { ServerConfig } from '../../../config/server-config.js';
|
|
12
12
|
import type { BrapiClient, BrapiEnvelope, BrapiPagination, BrapiRequestOptions, ResolvedAuth } from '../../../services/brapi-client/index.js';
|
|
13
13
|
import type { BrapiDialect } from '../../../services/brapi-dialect/index.js';
|
|
14
|
+
import type { CanvasBridge, RegisterDataframeResult } from '../../../services/canvas-bridge/index.js';
|
|
14
15
|
import type { CapabilityProfile } from '../../../services/capability-registry/types.js';
|
|
15
|
-
import type { DatasetMetadata, DatasetStore } from '../../../services/dataset-store/index.js';
|
|
16
16
|
import type { RegisteredServer } from '../../../services/server-registry/index.js';
|
|
17
17
|
/** True when the thrown value is an upstream 404 surfaced by the BrAPI client. */
|
|
18
18
|
export declare function isUpstreamNotFound(err: unknown): boolean;
|
|
19
|
-
/** Upper cap on how many rows we'll pull for
|
|
19
|
+
/** Upper cap on how many rows we'll pull for canvas dataframe spillover per call. */
|
|
20
20
|
export declare const MAX_SPILLOVER_ROWS = 50000;
|
|
21
|
-
/** Hard cap on how many BrAPI pages we'll traverse when building a
|
|
21
|
+
/** Hard cap on how many BrAPI pages we'll traverse when building a dataframe. */
|
|
22
22
|
export declare const MAX_SPILLOVER_PAGES = 50;
|
|
23
23
|
export declare const AliasInput: z.ZodOptional<z.ZodString>;
|
|
24
24
|
export declare const LoadLimitInput: z.ZodOptional<z.ZodNumber>;
|
|
@@ -90,18 +90,18 @@ export declare function companionRequestOptions(connection: RegisteredServer, di
|
|
|
90
90
|
*/
|
|
91
91
|
export declare function computeDistribution<T>(rows: readonly T[], accessor: (row: T) => string | readonly string[] | undefined | null): Record<string, number>;
|
|
92
92
|
/**
|
|
93
|
-
* Render the standardized header line for `find_*` tools. When a
|
|
94
|
-
* spillover is present, surfaces the
|
|
93
|
+
* Render the standardized header line for `find_*` tools. When a dataframe
|
|
94
|
+
* spillover is present, surfaces the dataframe row count alongside the
|
|
95
95
|
* in-context count and the upstream total — `{returned} of {total}` alone
|
|
96
96
|
* hides the middle number and confuses readers when filters miss server-
|
|
97
|
-
* side and the
|
|
97
|
+
* side and the dataframe row count diverges from both.
|
|
98
98
|
*/
|
|
99
99
|
export declare function renderFindHeader(opts: {
|
|
100
100
|
noun: string;
|
|
101
101
|
alias: string;
|
|
102
102
|
returnedCount: number;
|
|
103
103
|
totalCount: number;
|
|
104
|
-
|
|
104
|
+
dataframe?: {
|
|
105
105
|
rowCount: number;
|
|
106
106
|
expiresAt?: string;
|
|
107
107
|
} | undefined;
|
|
@@ -127,12 +127,13 @@ export interface LoadedRows<T> {
|
|
|
127
127
|
/**
|
|
128
128
|
* Pull rows up to `loadLimit` on a single page. If the server reports more
|
|
129
129
|
* rows than the limit, leave the rest behind — callers decide whether to
|
|
130
|
-
* spill via `
|
|
130
|
+
* spill via `spillToCanvas`.
|
|
131
131
|
*/
|
|
132
132
|
export declare function loadInitialPage<T>(client: BrapiClient, connection: RegisteredServer, path: string, filters: Record<string, unknown>, loadLimit: number, ctx: Context): Promise<LoadedRows<T>>;
|
|
133
133
|
/** Pull the first page for either a GET list endpoint or POST /search route. */
|
|
134
134
|
export declare function loadInitialFindPage<T>(client: BrapiClient, connection: RegisteredServer, route: FindRoute, loadLimit: number, ctx: Context): Promise<LoadedRows<T>>;
|
|
135
135
|
export interface SpillInput<T> {
|
|
136
|
+
bridge: CanvasBridge;
|
|
136
137
|
client: BrapiClient;
|
|
137
138
|
connection: RegisteredServer;
|
|
138
139
|
ctx: Context;
|
|
@@ -147,8 +148,8 @@ export interface SpillInput<T> {
|
|
|
147
148
|
route?: FindRoute;
|
|
148
149
|
/**
|
|
149
150
|
* Optional client-side predicate applied to every row (first-page + spilled)
|
|
150
|
-
* before persistence. When present, only rows that pass are
|
|
151
|
-
*
|
|
151
|
+
* before persistence. When present, only rows that pass are registered on
|
|
152
|
+
* the canvas and returned in `fullRows`. The unfiltered upstream total is
|
|
152
153
|
* preserved separately on the LoadedRows envelope so distributions and
|
|
153
154
|
* headers can still report the true upstream size.
|
|
154
155
|
*/
|
|
@@ -157,54 +158,53 @@ export interface SpillInput<T> {
|
|
|
157
158
|
* Optional client-side transform applied to every row (first-page + spilled)
|
|
158
159
|
* before any predicate filter runs. Used to normalize sparse / duplicated
|
|
159
160
|
* upstream payloads (e.g. dedup'ing CassavaBase's 11×-repeated synonym
|
|
160
|
-
* arrays) so the in-context view
|
|
161
|
-
*
|
|
161
|
+
* arrays) so the in-context view and the canvas dataframe see the same
|
|
162
|
+
* cleaned shape. Runs before `rowFilter`.
|
|
162
163
|
*/
|
|
163
164
|
rowMapper?: (row: T) => T;
|
|
164
165
|
source: string;
|
|
165
|
-
store: DatasetStore;
|
|
166
166
|
/** Total reported by the server on the first page. */
|
|
167
167
|
totalCount: number;
|
|
168
168
|
}
|
|
169
169
|
export interface SpillResult<T> {
|
|
170
|
-
|
|
171
|
-
/** Rows that were
|
|
170
|
+
dataframe: RegisterDataframeResult;
|
|
171
|
+
/** Rows that were registered (post-filter when `rowFilter` was supplied). */
|
|
172
172
|
fullRows: T[];
|
|
173
173
|
pagesFetched: number;
|
|
174
174
|
}
|
|
175
175
|
/**
|
|
176
|
-
* Shape of the
|
|
177
|
-
*
|
|
178
|
-
*
|
|
176
|
+
* Shape of the dataframe handle returned inline by `find_*` tools. The
|
|
177
|
+
* dataframe is the canvas table holding every row beyond `loadLimit`; query
|
|
178
|
+
* it with `brapi_dataframe_query` for SQL access or describe it with
|
|
179
|
+
* `brapi_dataframe_describe` for schema + provenance.
|
|
179
180
|
*/
|
|
180
|
-
export declare const
|
|
181
|
-
|
|
181
|
+
export declare const DataframeHandleSchema: z.ZodObject<{
|
|
182
|
+
tableName: z.ZodString;
|
|
182
183
|
rowCount: z.ZodNumber;
|
|
183
|
-
sizeBytes: z.ZodNumber;
|
|
184
184
|
columns: z.ZodArray<z.ZodString>;
|
|
185
185
|
createdAt: z.ZodString;
|
|
186
186
|
expiresAt: z.ZodString;
|
|
187
187
|
truncated: z.ZodOptional<z.ZodBoolean>;
|
|
188
188
|
maxRows: z.ZodOptional<z.ZodNumber>;
|
|
189
|
-
dataframe: z.ZodOptional<z.ZodString>;
|
|
190
189
|
}, z.core.$strip>;
|
|
191
|
-
export type
|
|
190
|
+
export type DataframeHandle = z.infer<typeof DataframeHandleSchema>;
|
|
192
191
|
/**
|
|
193
|
-
* Render a
|
|
192
|
+
* Render a DataframeHandle as bullet lines, matching the existing find_* tool
|
|
194
193
|
* format. Centralized so the truncated/maxRows fields surface consistently.
|
|
195
194
|
* `expiresAt` is paired with a human-readable `expires in Xh / Xd` so the
|
|
196
195
|
* agent doesn't have to subtract dates to know when the handle goes stale.
|
|
197
196
|
*/
|
|
198
|
-
export declare function
|
|
197
|
+
export declare function renderDataframeHandle(handle: DataframeHandle): string[];
|
|
199
198
|
/**
|
|
200
199
|
* Render an absolute `expiresAt` timestamp as a relative human label
|
|
201
200
|
* (`expires in 24h`, `expires in 30m`, `expired 5m ago`). Coarsens to the
|
|
202
201
|
* most useful unit so the value reads at a glance.
|
|
203
202
|
*/
|
|
204
203
|
export declare function formatExpiresIn(expiresAt: string, now?: Date): string;
|
|
205
|
-
/** Project a `
|
|
206
|
-
export declare function
|
|
204
|
+
/** Project a `RegisterDataframeResult` to the inline handle shape. */
|
|
205
|
+
export declare function toDataframeHandle(result: RegisterDataframeResult): DataframeHandle;
|
|
207
206
|
export interface MaybeSpillInput<T> {
|
|
207
|
+
bridge: CanvasBridge;
|
|
208
208
|
client: BrapiClient;
|
|
209
209
|
connection: RegisteredServer;
|
|
210
210
|
ctx: Context;
|
|
@@ -215,7 +215,7 @@ export interface MaybeSpillInput<T> {
|
|
|
215
215
|
route?: FindRoute;
|
|
216
216
|
/**
|
|
217
217
|
* Optional client-side predicate applied to every row before persistence.
|
|
218
|
-
* Forwarded to `
|
|
218
|
+
* Forwarded to `spillToCanvas`. When present and no spillover happens, the
|
|
219
219
|
* first-page rows are also filtered before being returned.
|
|
220
220
|
*/
|
|
221
221
|
rowFilter?: (row: T) => boolean;
|
|
@@ -227,38 +227,49 @@ export interface MaybeSpillInput<T> {
|
|
|
227
227
|
source: string;
|
|
228
228
|
/**
|
|
229
229
|
* Optional request overrides for spillover page pulls. Useful when a tool
|
|
230
|
-
* wants
|
|
231
|
-
*
|
|
230
|
+
* wants dataframe materialization to run under a tighter latency budget
|
|
231
|
+
* than the first page.
|
|
232
232
|
*/
|
|
233
233
|
spillRequestOptions?: BrapiRequestOptions;
|
|
234
|
-
store: DatasetStore;
|
|
235
234
|
/** Optional warning sink. When supplied, spillover failures degrade to rows-only output. */
|
|
236
235
|
warnings?: string[];
|
|
237
236
|
}
|
|
238
237
|
export interface MaybeSpillResult<T> {
|
|
239
|
-
|
|
238
|
+
dataframe?: DataframeHandle;
|
|
240
239
|
/** Row set after `rowFilter` (when supplied), spilled or first-page only. */
|
|
241
240
|
fullRows: T[];
|
|
242
241
|
}
|
|
243
242
|
/**
|
|
244
|
-
* Wrap `
|
|
243
|
+
* Wrap `spillToCanvas` with the "only spill when hasMore and totalCount >
|
|
245
244
|
* loadLimit" guard that every `find_*` tool replicates. When no spillover is
|
|
246
|
-
* needed, returns the first-page rows untouched. When it is,
|
|
247
|
-
* union
|
|
245
|
+
* needed, returns the first-page rows untouched. When it is, materializes
|
|
246
|
+
* the union as a canvas dataframe and returns both the full set and the
|
|
247
|
+
* handle.
|
|
248
248
|
*/
|
|
249
249
|
export declare function maybeSpill<T extends Record<string, unknown>>(input: MaybeSpillInput<T>): Promise<MaybeSpillResult<T>>;
|
|
250
250
|
/**
|
|
251
|
-
* Pull every remaining page up to MAX_SPILLOVER_* caps, then
|
|
252
|
-
* union
|
|
253
|
-
* (so callers can compute honest distributions from the whole result).
|
|
251
|
+
* Pull every remaining page up to MAX_SPILLOVER_* caps, then materialize the
|
|
252
|
+
* union as a canvas dataframe. Returns the dataframe metadata plus the full
|
|
253
|
+
* row set (so callers can compute honest distributions from the whole result).
|
|
254
254
|
*/
|
|
255
|
-
export declare function
|
|
255
|
+
export declare function spillToCanvas<T extends Record<string, unknown>>(input: SpillInput<T>): Promise<SpillResult<T>>;
|
|
256
256
|
/** BrAPI list endpoints return `{data: T[], ...}`. Some omit the wrapper. */
|
|
257
257
|
export interface BrapiListResult<T> {
|
|
258
258
|
data?: T[];
|
|
259
259
|
[key: string]: unknown;
|
|
260
260
|
}
|
|
261
261
|
export declare function extractRows<T>(result: BrapiListResult<T> | T[]): T[];
|
|
262
|
+
/**
|
|
263
|
+
* Extract a homogeneous record-row set from a raw BrAPI envelope `result`.
|
|
264
|
+
* Returns the array when `result` is itself a list of objects, or when
|
|
265
|
+
* `result.data` is — covering both bare-array and BrAPI-list-envelope shapes.
|
|
266
|
+
* Returns `null` for non-list shapes (single object, scalar, primitive
|
|
267
|
+
* arrays) so callers — notably `raw_get` / `raw_search` — can skip spillover
|
|
268
|
+
* and pass the upstream payload through unchanged. Empty arrays are list-
|
|
269
|
+
* shaped but carry no rows; the caller uses `length === 0` to decide whether
|
|
270
|
+
* to register a dataframe.
|
|
271
|
+
*/
|
|
272
|
+
export declare function extractListRows<T extends Record<string, unknown>>(result: unknown): T[] | null;
|
|
262
273
|
/** Return the input as a non-empty string, or undefined. Used in distribution accessors. */
|
|
263
274
|
export declare function asString(value: unknown): string | undefined;
|
|
264
275
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"find-helpers.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/shared/find-helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,KAAK,OAAO,EAAE,KAAK,cAAc,EAAE,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAE9E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EACV,WAAW,EACX,aAAa,EACb,eAAe,EACf,mBAAmB,EACnB,YAAY,EACb,MAAM,kCAAkC,CAAC;AAC1C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"find-helpers.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/shared/find-helpers.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
* @fileoverview Shared building blocks for `find_*` tools — Zod fragments for
|
|
3
3
|
* common inputs (alias, loadLimit, extraFilters), utilities to merge named
|
|
4
4
|
* filters with the passthrough map, a generic distribution aggregator, and
|
|
5
|
-
* the
|
|
6
|
-
*
|
|
5
|
+
* the spillover handler that turns a "too many rows" result into a canvas
|
|
6
|
+
* dataframe handle.
|
|
7
7
|
*
|
|
8
8
|
* @module mcp-server/tools/shared/find-helpers
|
|
9
9
|
*/
|
|
@@ -13,9 +13,9 @@ import { JsonRpcErrorCode, McpError, validationError } from '@cyanheads/mcp-ts-c
|
|
|
13
13
|
export function isUpstreamNotFound(err) {
|
|
14
14
|
return err instanceof McpError && err.code === JsonRpcErrorCode.NotFound;
|
|
15
15
|
}
|
|
16
|
-
/** Upper cap on how many rows we'll pull for
|
|
16
|
+
/** Upper cap on how many rows we'll pull for canvas dataframe spillover per call. */
|
|
17
17
|
export const MAX_SPILLOVER_ROWS = 50_000;
|
|
18
|
-
/** Hard cap on how many BrAPI pages we'll traverse when building a
|
|
18
|
+
/** Hard cap on how many BrAPI pages we'll traverse when building a dataframe. */
|
|
19
19
|
export const MAX_SPILLOVER_PAGES = 50;
|
|
20
20
|
export const AliasInput = z
|
|
21
21
|
.string()
|
|
@@ -27,7 +27,7 @@ export const LoadLimitInput = z
|
|
|
27
27
|
.int()
|
|
28
28
|
.positive()
|
|
29
29
|
.optional()
|
|
30
|
-
.describe('
|
|
30
|
+
.describe('Cap on rows returned inline. Omit for the deployment default — sized so spillover reaches its full row-count ceiling. Rows beyond the cap land in a dataframe; query with brapi_dataframe_query (SQL) instead of paging row-by-row. Heads-up: this same value drives the upstream pageSize during spillover walks, so lowering it to "preview a smaller sample" also shrinks the dataframe ceiling proportionally — prefer SQL `LIMIT` on the dataframe for sampling instead.');
|
|
31
31
|
export const ExtraFiltersInput = z
|
|
32
32
|
.record(z.string(), z.unknown())
|
|
33
33
|
.optional()
|
|
@@ -199,16 +199,18 @@ export function computeDistribution(rows, accessor) {
|
|
|
199
199
|
return Object.fromEntries([...counts.entries()].sort(([, a], [, b]) => b - a));
|
|
200
200
|
}
|
|
201
201
|
/**
|
|
202
|
-
* Render the standardized header line for `find_*` tools. When a
|
|
203
|
-
* spillover is present, surfaces the
|
|
202
|
+
* Render the standardized header line for `find_*` tools. When a dataframe
|
|
203
|
+
* spillover is present, surfaces the dataframe row count alongside the
|
|
204
204
|
* in-context count and the upstream total — `{returned} of {total}` alone
|
|
205
205
|
* hides the middle number and confuses readers when filters miss server-
|
|
206
|
-
* side and the
|
|
206
|
+
* side and the dataframe row count diverges from both.
|
|
207
207
|
*/
|
|
208
208
|
export function renderFindHeader(opts) {
|
|
209
|
-
if (opts.
|
|
210
|
-
const expiry = opts.
|
|
211
|
-
|
|
209
|
+
if (opts.dataframe) {
|
|
210
|
+
const expiry = opts.dataframe.expiresAt
|
|
211
|
+
? ` (${formatExpiresIn(opts.dataframe.expiresAt)})`
|
|
212
|
+
: '';
|
|
213
|
+
return `# ${opts.returnedCount} returned · ${opts.dataframe.rowCount} in dataframe${expiry} · ${opts.totalCount} total ${opts.noun} — \`${opts.alias}\``;
|
|
212
214
|
}
|
|
213
215
|
return `# ${opts.returnedCount} of ${opts.totalCount} ${opts.noun} — \`${opts.alias}\``;
|
|
214
216
|
}
|
|
@@ -249,7 +251,7 @@ export function renderDistributions(distributions) {
|
|
|
249
251
|
/**
|
|
250
252
|
* Pull rows up to `loadLimit` on a single page. If the server reports more
|
|
251
253
|
* rows than the limit, leave the rest behind — callers decide whether to
|
|
252
|
-
* spill via `
|
|
254
|
+
* spill via `spillToCanvas`.
|
|
253
255
|
*/
|
|
254
256
|
export async function loadInitialPage(client, connection, path, filters, loadLimit, ctx) {
|
|
255
257
|
return await loadInitialFindPage(client, connection, getRouteForPath(path, filters), loadLimit, ctx);
|
|
@@ -283,45 +285,48 @@ async function fetchFindRoutePage(client, connection, route, pageSize, page, ctx
|
|
|
283
285
|
return await client.getSearchResults(connection.baseUrl, route.noun, response.searchResultsDbId, ctx, buildRequestOptions(connection, { pageSize, page }, requestOptions));
|
|
284
286
|
}
|
|
285
287
|
/**
|
|
286
|
-
* Shape of the
|
|
287
|
-
*
|
|
288
|
-
*
|
|
288
|
+
* Shape of the dataframe handle returned inline by `find_*` tools. The
|
|
289
|
+
* dataframe is the canvas table holding every row beyond `loadLimit`; query
|
|
290
|
+
* it with `brapi_dataframe_query` for SQL access or describe it with
|
|
291
|
+
* `brapi_dataframe_describe` for schema + provenance.
|
|
289
292
|
*/
|
|
290
|
-
export const
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
293
|
+
export const DataframeHandleSchema = z.object({
|
|
294
|
+
tableName: z
|
|
295
|
+
.string()
|
|
296
|
+
.describe('Dataframe name. Use with brapi_dataframe_describe (schema + provenance) and brapi_dataframe_query (SQL).'),
|
|
297
|
+
rowCount: z
|
|
298
|
+
.number()
|
|
299
|
+
.int()
|
|
300
|
+
.nonnegative()
|
|
301
|
+
.describe('Number of rows materialized in the dataframe.'),
|
|
294
302
|
columns: z
|
|
295
|
-
.array(z.string().describe('Column name from the
|
|
296
|
-
.describe('Full column list of the
|
|
297
|
-
createdAt: z.string().describe('ISO 8601 timestamp the
|
|
298
|
-
expiresAt: z
|
|
303
|
+
.array(z.string().describe('Column name from the materialized rows.'))
|
|
304
|
+
.describe('Full column list of the dataframe.'),
|
|
305
|
+
createdAt: z.string().describe('ISO 8601 timestamp the dataframe was created.'),
|
|
306
|
+
expiresAt: z
|
|
307
|
+
.string()
|
|
308
|
+
.describe('ISO 8601 timestamp after which the dataframe metadata will be purged. Re-run the find_* tool to refresh, or copy results out before expiry.'),
|
|
299
309
|
truncated: z
|
|
300
310
|
.boolean()
|
|
301
311
|
.optional()
|
|
302
|
-
.describe('True when the
|
|
312
|
+
.describe('True when the dataframe hit a row cap before exhausting upstream.'),
|
|
303
313
|
maxRows: z
|
|
304
314
|
.number()
|
|
305
315
|
.int()
|
|
306
316
|
.positive()
|
|
307
317
|
.optional()
|
|
308
318
|
.describe('Cap that was applied at create time, when truncation occurred.'),
|
|
309
|
-
dataframe: z
|
|
310
|
-
.string()
|
|
311
|
-
.optional()
|
|
312
|
-
.describe('Dataframe name when this dataset was auto-registered as a SQL-queryable dataframe. Use with brapi_dataframe_query to run SQL across the rows.'),
|
|
313
319
|
});
|
|
314
320
|
/**
|
|
315
|
-
* Render a
|
|
321
|
+
* Render a DataframeHandle as bullet lines, matching the existing find_* tool
|
|
316
322
|
* format. Centralized so the truncated/maxRows fields surface consistently.
|
|
317
323
|
* `expiresAt` is paired with a human-readable `expires in Xh / Xd` so the
|
|
318
324
|
* agent doesn't have to subtract dates to know when the handle goes stale.
|
|
319
325
|
*/
|
|
320
|
-
export function
|
|
326
|
+
export function renderDataframeHandle(handle) {
|
|
321
327
|
const lines = [
|
|
322
|
-
`-
|
|
328
|
+
`- tableName: \`${handle.tableName}\` (query via brapi_dataframe_query)`,
|
|
323
329
|
`- rowCount: ${handle.rowCount}`,
|
|
324
|
-
`- sizeBytes: ${handle.sizeBytes}`,
|
|
325
330
|
`- columns: ${handle.columns.join(', ')}`,
|
|
326
331
|
`- createdAt: ${handle.createdAt}`,
|
|
327
332
|
`- expiresAt: ${handle.expiresAt} (${formatExpiresIn(handle.expiresAt)})`,
|
|
@@ -330,9 +335,6 @@ export function renderDatasetHandle(handle) {
|
|
|
330
335
|
lines.push(`- truncated: true`);
|
|
331
336
|
if (typeof handle.maxRows === 'number')
|
|
332
337
|
lines.push(`- maxRows: ${handle.maxRows}`);
|
|
333
|
-
if (handle.dataframe) {
|
|
334
|
-
lines.push(`- dataframe: \`${handle.dataframe}\` (queryable via brapi_dataframe_query)`);
|
|
335
|
-
}
|
|
336
338
|
return lines;
|
|
337
339
|
}
|
|
338
340
|
/**
|
|
@@ -360,29 +362,27 @@ export function formatExpiresIn(expiresAt, now = new Date()) {
|
|
|
360
362
|
label = `${days}d`;
|
|
361
363
|
return deltaMs >= 0 ? `expires in ${label}` : `expired ${label} ago`;
|
|
362
364
|
}
|
|
363
|
-
/** Project a `
|
|
364
|
-
export function
|
|
365
|
+
/** Project a `RegisterDataframeResult` to the inline handle shape. */
|
|
366
|
+
export function toDataframeHandle(result) {
|
|
365
367
|
const handle = {
|
|
366
|
-
|
|
367
|
-
rowCount:
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
expiresAt: metadata.expiresAt,
|
|
368
|
+
tableName: result.tableName,
|
|
369
|
+
rowCount: result.rowCount,
|
|
370
|
+
columns: result.columns,
|
|
371
|
+
createdAt: result.createdAt,
|
|
372
|
+
expiresAt: result.expiresAt,
|
|
372
373
|
};
|
|
373
|
-
if (
|
|
374
|
+
if (result.truncated)
|
|
374
375
|
handle.truncated = true;
|
|
375
|
-
if (typeof
|
|
376
|
-
handle.maxRows =
|
|
377
|
-
if (metadata.dataframe)
|
|
378
|
-
handle.dataframe = metadata.dataframe;
|
|
376
|
+
if (typeof result.maxRows === 'number')
|
|
377
|
+
handle.maxRows = result.maxRows;
|
|
379
378
|
return handle;
|
|
380
379
|
}
|
|
381
380
|
/**
|
|
382
|
-
* Wrap `
|
|
381
|
+
* Wrap `spillToCanvas` with the "only spill when hasMore and totalCount >
|
|
383
382
|
* loadLimit" guard that every `find_*` tool replicates. When no spillover is
|
|
384
|
-
* needed, returns the first-page rows untouched. When it is,
|
|
385
|
-
* union
|
|
383
|
+
* needed, returns the first-page rows untouched. When it is, materializes
|
|
384
|
+
* the union as a canvas dataframe and returns both the full set and the
|
|
385
|
+
* handle.
|
|
386
386
|
*/
|
|
387
387
|
export async function maybeSpill(input) {
|
|
388
388
|
const { firstPage, rowMapper, rowFilter } = input;
|
|
@@ -392,7 +392,7 @@ export async function maybeSpill(input) {
|
|
|
392
392
|
return { fullRows: applyRowTransforms(firstPage.rows, rowMapper, rowFilter) };
|
|
393
393
|
}
|
|
394
394
|
const spillInput = {
|
|
395
|
-
|
|
395
|
+
bridge: input.bridge,
|
|
396
396
|
client: input.client,
|
|
397
397
|
connection: input.connection,
|
|
398
398
|
path: input.path,
|
|
@@ -412,16 +412,16 @@ export async function maybeSpill(input) {
|
|
|
412
412
|
if (input.spillRequestOptions)
|
|
413
413
|
spillInput.pageRequestOptions = input.spillRequestOptions;
|
|
414
414
|
try {
|
|
415
|
-
const spill = await
|
|
415
|
+
const spill = await spillToCanvas(spillInput);
|
|
416
416
|
return {
|
|
417
417
|
fullRows: spill.fullRows,
|
|
418
|
-
|
|
418
|
+
dataframe: toDataframeHandle(spill.dataframe),
|
|
419
419
|
};
|
|
420
420
|
}
|
|
421
421
|
catch (err) {
|
|
422
422
|
if (!input.warnings || !(err instanceof SpillPageFetchError))
|
|
423
423
|
throw err;
|
|
424
|
-
input.warnings.push(`
|
|
424
|
+
input.warnings.push(`Dataframe spillover skipped after returning the first ${firstPage.rows.length} row(s): ${formatSpillError(err)}. Narrow filters, raise loadLimit enough to fit the result in one page, or retry when the upstream server is responsive.`);
|
|
425
425
|
return { fullRows: applyRowTransforms(firstPage.rows, rowMapper, rowFilter) };
|
|
426
426
|
}
|
|
427
427
|
}
|
|
@@ -429,18 +429,18 @@ export async function maybeSpill(input) {
|
|
|
429
429
|
* Apply mapper before filter on a row set. Centralizes the order constraint
|
|
430
430
|
* across the three spillover sites — early-exit, error fallback, and persist
|
|
431
431
|
* — so they can't drift apart and accidentally filter raw rows the spilled
|
|
432
|
-
*
|
|
432
|
+
* dataframe has already normalized.
|
|
433
433
|
*/
|
|
434
434
|
function applyRowTransforms(rows, mapper, filter) {
|
|
435
435
|
const mapped = mapper ? rows.map(mapper) : rows;
|
|
436
436
|
return filter ? mapped.filter(filter) : mapped;
|
|
437
437
|
}
|
|
438
438
|
/**
|
|
439
|
-
* Pull every remaining page up to MAX_SPILLOVER_* caps, then
|
|
440
|
-
* union
|
|
441
|
-
* (so callers can compute honest distributions from the whole result).
|
|
439
|
+
* Pull every remaining page up to MAX_SPILLOVER_* caps, then materialize the
|
|
440
|
+
* union as a canvas dataframe. Returns the dataframe metadata plus the full
|
|
441
|
+
* row set (so callers can compute honest distributions from the whole result).
|
|
442
442
|
*/
|
|
443
|
-
export async function
|
|
443
|
+
export async function spillToCanvas(input) {
|
|
444
444
|
const remainingTarget = Math.min(input.totalCount, MAX_SPILLOVER_ROWS);
|
|
445
445
|
const pageSize = input.loadLimit;
|
|
446
446
|
const totalPages = Math.min(Math.ceil(remainingTarget / pageSize), MAX_SPILLOVER_PAGES);
|
|
@@ -470,23 +470,23 @@ export async function spillToDataset(input) {
|
|
|
470
470
|
const reachedPageCap = pagesFetched >= MAX_SPILLOVER_PAGES && input.totalCount > rows.length;
|
|
471
471
|
const truncated = reachedRowCap || reachedPageCap;
|
|
472
472
|
const persistedRows = applyRowTransforms(rows, input.rowMapper, input.rowFilter);
|
|
473
|
-
const
|
|
473
|
+
const registerInput = {
|
|
474
474
|
source: input.source,
|
|
475
475
|
baseUrl: input.connection.baseUrl,
|
|
476
476
|
query: input.filters,
|
|
477
477
|
rows: persistedRows,
|
|
478
478
|
};
|
|
479
479
|
if (truncated) {
|
|
480
|
-
|
|
480
|
+
registerInput.truncated = true;
|
|
481
481
|
// `maxRows` only carries meaning when the row cap fired — it's the upper
|
|
482
482
|
// bound the spillover honored. When the page cap fired first (small
|
|
483
483
|
// `loadLimit` × `MAX_SPILLOVER_PAGES` < upstream total), reporting
|
|
484
|
-
// `maxRows = MAX_SPILLOVER_ROWS` is misleading: the
|
|
484
|
+
// `maxRows = MAX_SPILLOVER_ROWS` is misleading: the dataframe stopped at
|
|
485
485
|
// `loadLimit × MAX_SPILLOVER_PAGES`, well below the row cap. Log the
|
|
486
486
|
// page-cap event for operators; the agent sees only `truncated: true`
|
|
487
487
|
// without the false 50k bound and can raise `loadLimit` to push past it.
|
|
488
488
|
if (reachedRowCap) {
|
|
489
|
-
|
|
489
|
+
registerInput.maxRows = MAX_SPILLOVER_ROWS;
|
|
490
490
|
}
|
|
491
491
|
else if (reachedPageCap) {
|
|
492
492
|
input.ctx.log.warning('Spillover hit page cap before exhausting upstream', {
|
|
@@ -498,8 +498,8 @@ export async function spillToDataset(input) {
|
|
|
498
498
|
});
|
|
499
499
|
}
|
|
500
500
|
}
|
|
501
|
-
const
|
|
502
|
-
return {
|
|
501
|
+
const dataframe = await input.bridge.registerDataframe(input.ctx, registerInput);
|
|
502
|
+
return { dataframe, fullRows: persistedRows, pagesFetched };
|
|
503
503
|
}
|
|
504
504
|
class SpillPageFetchError extends Error {
|
|
505
505
|
name = 'SpillPageFetchError';
|
|
@@ -526,6 +526,29 @@ export function extractRows(result) {
|
|
|
526
526
|
return result.data;
|
|
527
527
|
return [];
|
|
528
528
|
}
|
|
529
|
+
/**
|
|
530
|
+
* Extract a homogeneous record-row set from a raw BrAPI envelope `result`.
|
|
531
|
+
* Returns the array when `result` is itself a list of objects, or when
|
|
532
|
+
* `result.data` is — covering both bare-array and BrAPI-list-envelope shapes.
|
|
533
|
+
* Returns `null` for non-list shapes (single object, scalar, primitive
|
|
534
|
+
* arrays) so callers — notably `raw_get` / `raw_search` — can skip spillover
|
|
535
|
+
* and pass the upstream payload through unchanged. Empty arrays are list-
|
|
536
|
+
* shaped but carry no rows; the caller uses `length === 0` to decide whether
|
|
537
|
+
* to register a dataframe.
|
|
538
|
+
*/
|
|
539
|
+
export function extractListRows(result) {
|
|
540
|
+
const candidate = Array.isArray(result)
|
|
541
|
+
? result
|
|
542
|
+
: result && typeof result === 'object' && Array.isArray(result.data)
|
|
543
|
+
? result.data
|
|
544
|
+
: null;
|
|
545
|
+
if (candidate === null)
|
|
546
|
+
return null;
|
|
547
|
+
if (candidate.length === 0)
|
|
548
|
+
return [];
|
|
549
|
+
const allObjects = candidate.every((row) => typeof row === 'object' && row !== null && !Array.isArray(row));
|
|
550
|
+
return allObjects ? candidate : null;
|
|
551
|
+
}
|
|
529
552
|
/** Return the input as a non-empty string, or undefined. Used in distribution accessors. */
|
|
530
553
|
export function asString(value) {
|
|
531
554
|
return typeof value === 'string' && value.length > 0 ? value : undefined;
|