@cyanheads/brapi-mcp-server 0.4.13 → 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 +25 -19
- package/README.md +40 -26
- package/changelog/0.4.x/0.4.13.md +15 -0
- package/changelog/0.4.x/0.4.14.md +22 -0
- 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 +21 -17
- 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 +60 -19
- 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-get-germplasm.tool.d.ts.map +1 -1
- package/dist/mcp-server/tools/definitions/brapi-get-germplasm.tool.js +6 -2
- package/dist/mcp-server/tools/definitions/brapi-get-germplasm.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 +79 -39
- package/dist/mcp-server/tools/shared/find-helpers.d.ts.map +1 -1
- package/dist/mcp-server/tools/shared/find-helpers.js +167 -70
- 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 +220 -103
- 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
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview `brapi_dataframe_export` — write a dataframe to disk in a
|
|
3
|
+
* researcher-friendly format (CSV, Parquet, JSON) and return the absolute
|
|
4
|
+
* path. Hands off the file to the human; the agent doesn't read it back.
|
|
5
|
+
*
|
|
6
|
+
* Stdio-only and gated behind `BRAPI_EXPORT_DIR` — the entry point bridges
|
|
7
|
+
* `BRAPI_EXPORT_DIR` → the framework's `CANVAS_EXPORT_PATH` so the canvas
|
|
8
|
+
* provider's path-traversal sandbox stays in charge of resolution. Under
|
|
9
|
+
* `MCP_TRANSPORT_TYPE=http` or with `BRAPI_EXPORT_DIR` unset, the tool is
|
|
10
|
+
* omitted from `tools/list` entirely (operators see the gate reason on
|
|
11
|
+
* `/.well-known/mcp.json`).
|
|
12
|
+
*
|
|
13
|
+
* Optional `columns` (thin projection) or `sql` (full SELECT) materialize a
|
|
14
|
+
* temporary canvas table first, export it, then drop it. The dataframe input
|
|
15
|
+
* always identifies the *source* dataframe — that's the name the paired-drop
|
|
16
|
+
* cleanup keys off of when `brapi_dataframe_drop` later removes it.
|
|
17
|
+
*
|
|
18
|
+
* @module mcp-server/tools/definitions/brapi-dataframe-export.tool
|
|
19
|
+
*/
|
|
20
|
+
import { readdir, stat, unlink } from 'node:fs/promises';
|
|
21
|
+
import { join } from 'node:path';
|
|
22
|
+
import { tool, z } from '@cyanheads/mcp-ts-core';
|
|
23
|
+
import { JsonRpcErrorCode } from '@cyanheads/mcp-ts-core/errors';
|
|
24
|
+
import { getServerConfig } from '../../../config/server-config.js';
|
|
25
|
+
import { getCanvasBridge } from '../../../services/canvas-bridge/index.js';
|
|
26
|
+
const ColumnNameSchema = z
|
|
27
|
+
.string()
|
|
28
|
+
.regex(/^[A-Za-z_][A-Za-z0-9_]{0,62}$/)
|
|
29
|
+
.describe('Column name to project — letters, digits, underscores; must start with a letter or underscore; max 63 chars.');
|
|
30
|
+
const InputSchema = z.object({
|
|
31
|
+
dataframe: z
|
|
32
|
+
.string()
|
|
33
|
+
.min(1)
|
|
34
|
+
.describe('Dataframe to export. Use brapi_dataframe_describe to discover names. Source identity for the export — paired-drop cleanup keys off this name when brapi_dataframe_drop later removes it.'),
|
|
35
|
+
format: z
|
|
36
|
+
.enum(['csv', 'parquet', 'json'])
|
|
37
|
+
.describe('Output format. CSV opens in Excel / Tad; Parquet preserves typed columns and is small on disk; JSON is line-delimited.'),
|
|
38
|
+
filename: z
|
|
39
|
+
.string()
|
|
40
|
+
.min(1)
|
|
41
|
+
.optional()
|
|
42
|
+
.describe('Optional filename inside BRAPI_EXPORT_DIR. Path separators ("/", "\\") and ".." segments are rejected. Re-using a name overwrites the existing file. Omit to get a timestamp-suffixed default that never collides.'),
|
|
43
|
+
columns: z
|
|
44
|
+
.array(ColumnNameSchema)
|
|
45
|
+
.min(1)
|
|
46
|
+
.optional()
|
|
47
|
+
.describe('Optional thin projection — exports only these columns. Mutually exclusive with `sql`. For filtering or aggregation, run brapi_dataframe_query with registerAs first, then export that derived dataframe.'),
|
|
48
|
+
sql: z
|
|
49
|
+
.string()
|
|
50
|
+
.min(1)
|
|
51
|
+
.optional()
|
|
52
|
+
.describe('Optional SELECT statement that defines what to export — same SQL gate as brapi_dataframe_query (SELECT only, single statement, plan-walk allowlist). Mutually exclusive with `columns`. The dataframe input still identifies the source for paired-drop cleanup.'),
|
|
53
|
+
});
|
|
54
|
+
const ColumnInfoSchema = z.object({
|
|
55
|
+
name: z.string().describe('Column name in projection order.'),
|
|
56
|
+
type: z.string().describe('SQL/DuckDB column type (VARCHAR, BIGINT, DOUBLE, BOOLEAN, JSON, …).'),
|
|
57
|
+
});
|
|
58
|
+
const OutputSchema = z.object({
|
|
59
|
+
dataframe: z.string().describe('Source dataframe the export was derived from.'),
|
|
60
|
+
format: z.enum(['csv', 'parquet', 'json']).describe('Format that was written.'),
|
|
61
|
+
path: z.string().describe('Absolute path to the export file on the host filesystem.'),
|
|
62
|
+
filename: z.string().describe('Filename inside BRAPI_EXPORT_DIR (basename only).'),
|
|
63
|
+
sizeBytes: z.number().int().nonnegative().describe('Bytes written.'),
|
|
64
|
+
rowCount: z.number().int().nonnegative().describe('Rows written to the file.'),
|
|
65
|
+
columns: z
|
|
66
|
+
.array(ColumnInfoSchema.describe('One column descriptor — name and SQL/DuckDB type.'))
|
|
67
|
+
.describe('Column metadata for the exported file in projection order.'),
|
|
68
|
+
expiresAt: z
|
|
69
|
+
.string()
|
|
70
|
+
.describe('ISO 8601 staleness hint — when the source dataframe will TTL out and any paired sweep will reap this file. The file itself persists on disk independently.'),
|
|
71
|
+
});
|
|
72
|
+
export const brapiDataframeExport = tool('brapi_dataframe_export', {
|
|
73
|
+
description: 'Export a dataframe to disk (CSV, Parquet, or JSON) under BRAPI_EXPORT_DIR and return the absolute path of a file the human can open in Excel, Tad, DuckDB CLI, etc. Source dataframes are immutable after spillover, so re-exporting the same df_<uuid> is byte-stable. Use `columns` for thin projection or `sql` for filtering/aggregation; for repeated derived views, query with registerAs first then export the derived dataframe.',
|
|
74
|
+
annotations: { readOnlyHint: false, idempotentHint: false, openWorldHint: false },
|
|
75
|
+
errors: [
|
|
76
|
+
{
|
|
77
|
+
reason: 'export_dir_unset',
|
|
78
|
+
code: JsonRpcErrorCode.ConfigurationError,
|
|
79
|
+
when: 'BRAPI_EXPORT_DIR is not configured (defensive — the registration gate normally hides the tool when this happens)',
|
|
80
|
+
recovery: 'Set BRAPI_EXPORT_DIR on the server before retrying.',
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
reason: 'dataframe_not_found',
|
|
84
|
+
code: JsonRpcErrorCode.NotFound,
|
|
85
|
+
when: 'No dataframe with this name exists on the canvas (expired, dropped, or typo)',
|
|
86
|
+
recovery: 'Call brapi_dataframe_describe to list available dataframes.',
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
reason: 'invalid_filename',
|
|
90
|
+
code: JsonRpcErrorCode.ValidationError,
|
|
91
|
+
when: 'filename contains path separators or traversal segments',
|
|
92
|
+
recovery: 'Provide a filename without "/", "\\", or ".." — leave it unset to use the default.',
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
reason: 'mutually_exclusive_projection',
|
|
96
|
+
code: JsonRpcErrorCode.ValidationError,
|
|
97
|
+
when: 'Both `columns` and `sql` were supplied',
|
|
98
|
+
recovery: 'Pass either `columns` for a thin projection or `sql` for filtering/aggregation, not both.',
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
input: InputSchema,
|
|
102
|
+
output: OutputSchema,
|
|
103
|
+
async handler(input, ctx) {
|
|
104
|
+
const config = getServerConfig();
|
|
105
|
+
if (!config.exportDir) {
|
|
106
|
+
throw ctx.fail('export_dir_unset', undefined, { ...ctx.recoveryFor('export_dir_unset') });
|
|
107
|
+
}
|
|
108
|
+
if (input.columns && input.sql) {
|
|
109
|
+
throw ctx.fail('mutually_exclusive_projection', undefined, {
|
|
110
|
+
...ctx.recoveryFor('mutually_exclusive_projection'),
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
const filename = resolveFilename(input, ctx);
|
|
114
|
+
const bridge = getCanvasBridge();
|
|
115
|
+
const sourceTables = await bridge.describe(ctx, { tableName: input.dataframe });
|
|
116
|
+
if (sourceTables.length === 0) {
|
|
117
|
+
throw ctx.fail('dataframe_not_found', `Dataframe "${input.dataframe}" not found.`, {
|
|
118
|
+
...ctx.recoveryFor('dataframe_not_found'),
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
await sweepStaleExports(config.exportDir, config.datasetTtlSeconds, ctx);
|
|
122
|
+
const projection = input.columns ?? input.sql;
|
|
123
|
+
const derivedName = projection !== undefined
|
|
124
|
+
? `_brapi_export_${crypto.randomUUID().replace(/-/g, '_')}`
|
|
125
|
+
: undefined;
|
|
126
|
+
const tableToExport = derivedName ?? input.dataframe;
|
|
127
|
+
if (derivedName !== undefined) {
|
|
128
|
+
const sql = input.sql ?? buildProjectionSql(input.dataframe, input.columns ?? []);
|
|
129
|
+
await bridge.query(ctx, sql, { registerAs: derivedName, preview: 1 });
|
|
130
|
+
}
|
|
131
|
+
let exportResult;
|
|
132
|
+
let exportedColumns;
|
|
133
|
+
try {
|
|
134
|
+
const exportTables = await bridge.describe(ctx, { tableName: tableToExport });
|
|
135
|
+
exportedColumns = (exportTables[0]?.columns ?? []).map((c) => ({
|
|
136
|
+
name: c.name,
|
|
137
|
+
type: c.type,
|
|
138
|
+
}));
|
|
139
|
+
exportResult = await bridge.export(ctx, tableToExport, { format: input.format, path: filename }, { signal: ctx.signal });
|
|
140
|
+
if (exportResult.path) {
|
|
141
|
+
await bridge.trackExport(ctx, input.dataframe, exportResult.path);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
finally {
|
|
145
|
+
if (derivedName !== undefined) {
|
|
146
|
+
try {
|
|
147
|
+
await bridge.drop(ctx, derivedName);
|
|
148
|
+
}
|
|
149
|
+
catch (err) {
|
|
150
|
+
ctx.log.warning('Failed to drop derived export-projection table', {
|
|
151
|
+
tableName: derivedName,
|
|
152
|
+
error: err instanceof Error ? err.message : String(err),
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return {
|
|
158
|
+
dataframe: input.dataframe,
|
|
159
|
+
format: input.format,
|
|
160
|
+
path: exportResult.path ?? '',
|
|
161
|
+
filename,
|
|
162
|
+
sizeBytes: exportResult.sizeBytes,
|
|
163
|
+
rowCount: exportResult.rowCount,
|
|
164
|
+
columns: exportedColumns,
|
|
165
|
+
expiresAt: sourceTables[0]?.provenance?.expiresAt ?? expiresAtFromConfig(config.datasetTtlSeconds),
|
|
166
|
+
};
|
|
167
|
+
},
|
|
168
|
+
format: (result) => [{ type: 'text', text: renderExport(result) }],
|
|
169
|
+
});
|
|
170
|
+
const FILENAME_REJECT = /[/\\]|^\.\.$|\.\.[/\\]|[/\\]\.\./;
|
|
171
|
+
function resolveFilename(input, ctx) {
|
|
172
|
+
if (input.filename !== undefined) {
|
|
173
|
+
if (FILENAME_REJECT.test(input.filename) || input.filename === '..') {
|
|
174
|
+
throw ctx.fail('invalid_filename', `Filename "${input.filename}" is not allowed.`, {
|
|
175
|
+
...ctx.recoveryFor('invalid_filename'),
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
return input.filename;
|
|
179
|
+
}
|
|
180
|
+
return defaultFilename(input.dataframe, input.format);
|
|
181
|
+
}
|
|
182
|
+
function defaultFilename(dataframe, format) {
|
|
183
|
+
const stamp = Math.floor(Date.now() / 1000);
|
|
184
|
+
return `${dataframe}-${stamp}.${format}`;
|
|
185
|
+
}
|
|
186
|
+
function buildProjectionSql(dataframe, columns) {
|
|
187
|
+
return `SELECT ${columns.join(', ')} FROM ${dataframe}`;
|
|
188
|
+
}
|
|
189
|
+
function expiresAtFromConfig(ttlSeconds) {
|
|
190
|
+
return new Date(Date.now() + ttlSeconds * 1000).toISOString();
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Best-effort sweep of stale export files. Walks `BRAPI_EXPORT_DIR` and
|
|
194
|
+
* unlinks any regular file with `mtime + ttlSeconds < now`. Errors are
|
|
195
|
+
* swallowed (including a missing directory — DuckDB's `mkdir` will create
|
|
196
|
+
* it on first export). Bounded work: typical export directories hold tens
|
|
197
|
+
* of files at most.
|
|
198
|
+
*/
|
|
199
|
+
async function sweepStaleExports(dir, ttlSeconds, ctx) {
|
|
200
|
+
try {
|
|
201
|
+
const entries = await readdir(dir);
|
|
202
|
+
const cutoff = Date.now() - ttlSeconds * 1000;
|
|
203
|
+
await Promise.allSettled(entries.map(async (name) => {
|
|
204
|
+
const path = join(dir, name);
|
|
205
|
+
try {
|
|
206
|
+
const info = await stat(path);
|
|
207
|
+
if (info.isFile() && info.mtimeMs < cutoff)
|
|
208
|
+
await unlink(path);
|
|
209
|
+
}
|
|
210
|
+
catch {
|
|
211
|
+
/* file vanished between stat and unlink — fine. */
|
|
212
|
+
}
|
|
213
|
+
}));
|
|
214
|
+
}
|
|
215
|
+
catch (err) {
|
|
216
|
+
ctx.log.debug('Export-dir sweep skipped', {
|
|
217
|
+
dir,
|
|
218
|
+
error: err instanceof Error ? err.message : String(err),
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
function renderExport(result) {
|
|
223
|
+
const lines = [];
|
|
224
|
+
lines.push(`# Exported \`${result.dataframe}\` → \`${result.filename}\``);
|
|
225
|
+
lines.push(`- format: ${result.format}`);
|
|
226
|
+
lines.push(`- path: ${result.path}`);
|
|
227
|
+
lines.push(`- rows: ${result.rowCount}`);
|
|
228
|
+
lines.push(`- bytes: ${result.sizeBytes}`);
|
|
229
|
+
lines.push(`- columns: ${result.columns.map((c) => `${c.name} (${c.type})`).join(', ')}`);
|
|
230
|
+
lines.push(`- expiresAt: ${result.expiresAt}`);
|
|
231
|
+
return lines.join('\n');
|
|
232
|
+
}
|
|
233
|
+
//# sourceMappingURL=brapi-dataframe-export.tool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"brapi-dataframe-export.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/brapi-dataframe-export.tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview `brapi_dataframe_query` — execute SQL across in-memory
|
|
3
|
-
* dataframes. Dataframes auto-populate when find_* tools spill
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
3
|
+
* dataframes. Dataframes auto-populate when find_* tools spill (each becomes
|
|
4
|
+
* `df_<uuid>`). SQL is the primary paging idiom — use `LIMIT/OFFSET` to walk
|
|
5
|
+
* a large dataframe, projection (`SELECT col1, col2`) to trim rows, and
|
|
6
|
+
* aggregation (`COUNT`, `GROUP BY`, `AVG`) to summarize without materializing
|
|
7
|
+
* every row in the LLM context. Use `registerAs` to materialize a result as
|
|
8
|
+
* a new dataframe — the response carries a bounded `preview` slice plus the
|
|
9
|
+
* full `rowCount`. Read-only enforcement is the framework's three-layer SQL
|
|
10
|
+
* gate (single statement → SELECT only → plan-walk allowlist).
|
|
11
|
+
*
|
|
12
|
+
* Every query runs under a `registerAs` so DuckDB's describe is the
|
|
13
|
+
* authoritative type source for the response columns. When the caller
|
|
14
|
+
* doesn't supply `registerAs`, the handler generates an internal
|
|
15
|
+
* `_brapi_probe_<uuid>` name, describes the materialized table for types,
|
|
16
|
+
* then drops it before returning — so types stay consistent with what
|
|
17
|
+
* `brapi_dataframe_describe` would report.
|
|
8
18
|
*
|
|
9
19
|
* Defaults to a fresh per-tenant default workspace; the agent never passes a
|
|
10
20
|
* canvasId. The bridge resolves it via `ctx.state` so multiple calls in the
|
|
@@ -21,15 +31,13 @@ export declare const brapiDataframeQuery: import("@cyanheads/mcp-ts-core").ToolD
|
|
|
21
31
|
rowLimit: z.ZodOptional<z.ZodNumber>;
|
|
22
32
|
}, z.core.$strip>, z.ZodObject<{
|
|
23
33
|
rowCount: z.ZodNumber;
|
|
24
|
-
columns: z.ZodArray<z.
|
|
34
|
+
columns: z.ZodArray<z.ZodObject<{
|
|
35
|
+
name: z.ZodString;
|
|
36
|
+
type: z.ZodString;
|
|
37
|
+
}, z.core.$strip>>;
|
|
25
38
|
rows: z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
26
39
|
dataframe: z.ZodOptional<z.ZodString>;
|
|
27
40
|
}, z.core.$strip>, readonly [{
|
|
28
|
-
readonly reason: "dataframe_disabled";
|
|
29
|
-
readonly code: JsonRpcErrorCode.ServiceUnavailable;
|
|
30
|
-
readonly when: "Dataframe surface is not enabled on this deployment";
|
|
31
|
-
readonly recovery: "Use brapi_manage_dataset (mode=load) to page rows from the underlying dataset — SQL across dataframes is gated off here.";
|
|
32
|
-
}, {
|
|
33
41
|
readonly reason: "sql_rejected";
|
|
34
42
|
readonly code: JsonRpcErrorCode.ValidationError;
|
|
35
43
|
readonly when: "SQL violated read-only rules (multi-statement, non-SELECT, or disallowed operation)";
|
|
@@ -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
|
|
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;AA2F3E,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;GAmE9B,CAAC"}
|
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview `brapi_dataframe_query` — execute SQL across in-memory
|
|
3
|
-
* dataframes. Dataframes auto-populate when find_* tools spill
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
3
|
+
* dataframes. Dataframes auto-populate when find_* tools spill (each becomes
|
|
4
|
+
* `df_<uuid>`). SQL is the primary paging idiom — use `LIMIT/OFFSET` to walk
|
|
5
|
+
* a large dataframe, projection (`SELECT col1, col2`) to trim rows, and
|
|
6
|
+
* aggregation (`COUNT`, `GROUP BY`, `AVG`) to summarize without materializing
|
|
7
|
+
* every row in the LLM context. Use `registerAs` to materialize a result as
|
|
8
|
+
* a new dataframe — the response carries a bounded `preview` slice plus the
|
|
9
|
+
* full `rowCount`. Read-only enforcement is the framework's three-layer SQL
|
|
10
|
+
* gate (single statement → SELECT only → plan-walk allowlist).
|
|
11
|
+
*
|
|
12
|
+
* Every query runs under a `registerAs` so DuckDB's describe is the
|
|
13
|
+
* authoritative type source for the response columns. When the caller
|
|
14
|
+
* doesn't supply `registerAs`, the handler generates an internal
|
|
15
|
+
* `_brapi_probe_<uuid>` name, describes the materialized table for types,
|
|
16
|
+
* then drops it before returning — so types stay consistent with what
|
|
17
|
+
* `brapi_dataframe_describe` would report.
|
|
8
18
|
*
|
|
9
19
|
* Defaults to a fresh per-tenant default workspace; the agent never passes a
|
|
10
20
|
* canvasId. The bridge resolves it via `ctx.state` so multiple calls in the
|
|
@@ -13,7 +23,7 @@
|
|
|
13
23
|
* @module mcp-server/tools/definitions/brapi-dataframe-query.tool
|
|
14
24
|
*/
|
|
15
25
|
import { tool, z } from '@cyanheads/mcp-ts-core';
|
|
16
|
-
import { SQL_GATE_REASONS, } from '@cyanheads/mcp-ts-core/canvas';
|
|
26
|
+
import { inferSchemaFromRows, SQL_GATE_REASONS, } from '@cyanheads/mcp-ts-core/canvas';
|
|
17
27
|
import { JsonRpcErrorCode, McpError } from '@cyanheads/mcp-ts-core/errors';
|
|
18
28
|
import { getCanvasBridge } from '../../../services/canvas-bridge/index.js';
|
|
19
29
|
/**
|
|
@@ -38,7 +48,7 @@ const InputSchema = z.object({
|
|
|
38
48
|
sql: z
|
|
39
49
|
.string()
|
|
40
50
|
.min(1)
|
|
41
|
-
.describe('SELECT statement against dataframes. Single statement only — writes, DDL, file reads, and exports are rejected. Use brapi_dataframe_describe to discover available dataframes.'),
|
|
51
|
+
.describe('SELECT statement against dataframes. Single statement only — writes, DDL, file reads, and exports are rejected. Use brapi_dataframe_describe to discover available dataframes. SQL is the primary paging idiom: use `LIMIT/OFFSET` to walk a large dataframe, projection to trim columns, and aggregation (`COUNT`, `GROUP BY`, `AVG`) to summarize without materializing every row.'),
|
|
42
52
|
registerAs: z
|
|
43
53
|
.string()
|
|
44
54
|
.regex(/^[A-Za-z_][A-Za-z0-9_]{0,62}$/)
|
|
@@ -58,6 +68,12 @@ const InputSchema = z.object({
|
|
|
58
68
|
.optional()
|
|
59
69
|
.describe('Hard cap on rows materialized into the response, bounded by the deployment-wide response cap. For larger result sets, use `registerAs` to keep the full result queryable instead of raising this.'),
|
|
60
70
|
});
|
|
71
|
+
const ColumnInfoSchema = z.object({
|
|
72
|
+
name: z.string().describe('Column name in projection order.'),
|
|
73
|
+
type: z
|
|
74
|
+
.string()
|
|
75
|
+
.describe('SQL/DuckDB column type (e.g. VARCHAR, BIGINT, DOUBLE, BOOLEAN, JSON) sourced from DuckDB schema metadata. The same type appears whether or not `registerAs` was supplied — without it, the handler runs an internal probe to recover authoritative types that would otherwise be lost when DuckDB BigInts serialize to JSON strings.'),
|
|
76
|
+
});
|
|
61
77
|
const OutputSchema = z.object({
|
|
62
78
|
rowCount: z
|
|
63
79
|
.number()
|
|
@@ -65,8 +81,8 @@ const OutputSchema = z.object({
|
|
|
65
81
|
.nonnegative()
|
|
66
82
|
.describe('Total rows the query produced (may exceed `rows.length` when capped).'),
|
|
67
83
|
columns: z
|
|
68
|
-
.array(
|
|
69
|
-
.describe('Column
|
|
84
|
+
.array(ColumnInfoSchema.describe('One column descriptor — name and SQL/DuckDB type.'))
|
|
85
|
+
.describe('Column metadata in projection order — name and SQL type. Use this to write follow-up queries without round-tripping through brapi_dataframe_describe.'),
|
|
70
86
|
rows: z
|
|
71
87
|
.array(z
|
|
72
88
|
.record(z.string(), z.unknown())
|
|
@@ -78,15 +94,9 @@ const OutputSchema = z.object({
|
|
|
78
94
|
.describe('Name of the dataframe holding the full result, populated when `registerAs` was supplied. Reference this name in follow-up queries.'),
|
|
79
95
|
});
|
|
80
96
|
export const brapiDataframeQuery = tool('brapi_dataframe_query', {
|
|
81
|
-
description: 'Run SQL across in-memory dataframes. Dataframes auto-populate when find_* tools spill (named `
|
|
97
|
+
description: 'Run SQL across in-memory dataframes. Dataframes auto-populate when find_* tools spill (named `df_<uuid>`); list them via brapi_dataframe_describe. SELECT only — writes/DDL/COPY/PRAGMA/ATTACH/file-reads are rejected. Use SQL as the paging idiom: `LIMIT/OFFSET` to walk results, projection to trim columns, aggregation to summarize. Use `registerAs` to chain — the result lands as a new dataframe.',
|
|
82
98
|
annotations: { readOnlyHint: false, idempotentHint: false, openWorldHint: false },
|
|
83
99
|
errors: [
|
|
84
|
-
{
|
|
85
|
-
reason: 'dataframe_disabled',
|
|
86
|
-
code: JsonRpcErrorCode.ServiceUnavailable,
|
|
87
|
-
when: 'Dataframe surface is not enabled on this deployment',
|
|
88
|
-
recovery: 'Use brapi_manage_dataset (mode=load) to page rows from the underlying dataset — SQL across dataframes is gated off here.',
|
|
89
|
-
},
|
|
90
100
|
{
|
|
91
101
|
reason: 'sql_rejected',
|
|
92
102
|
code: JsonRpcErrorCode.ValidationError,
|
|
@@ -98,14 +108,13 @@ export const brapiDataframeQuery = tool('brapi_dataframe_query', {
|
|
|
98
108
|
output: OutputSchema,
|
|
99
109
|
async handler(input, ctx) {
|
|
100
110
|
const bridge = getCanvasBridge();
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
111
|
+
const userRegisterAs = input.registerAs;
|
|
112
|
+
const probeName = userRegisterAs ?? `_brapi_probe_${crypto.randomUUID().replace(/-/g, '_')}`;
|
|
113
|
+
const queryOpts = {
|
|
114
|
+
registerAs: probeName,
|
|
115
|
+
};
|
|
105
116
|
if (input.preview !== undefined)
|
|
106
117
|
queryOpts.preview = input.preview;
|
|
107
|
-
if (input.registerAs !== undefined)
|
|
108
|
-
queryOpts.registerAs = input.registerAs;
|
|
109
118
|
if (input.rowLimit !== undefined)
|
|
110
119
|
queryOpts.rowLimit = input.rowLimit;
|
|
111
120
|
let result;
|
|
@@ -119,22 +128,65 @@ export const brapiDataframeQuery = tool('brapi_dataframe_query', {
|
|
|
119
128
|
const message = err instanceof Error ? err.message : 'Query rejected.';
|
|
120
129
|
throw ctx.fail('sql_rejected', message, { gateReason, ...ctx.recoveryFor('sql_rejected') }, { cause: err });
|
|
121
130
|
}
|
|
131
|
+
let typedColumns;
|
|
132
|
+
try {
|
|
133
|
+
typedColumns = await resolveTypedColumns(bridge, ctx, result, probeName);
|
|
134
|
+
}
|
|
135
|
+
finally {
|
|
136
|
+
if (userRegisterAs === undefined) {
|
|
137
|
+
try {
|
|
138
|
+
await bridge.drop(ctx, probeName);
|
|
139
|
+
}
|
|
140
|
+
catch (err) {
|
|
141
|
+
ctx.log.warning('Failed to drop ephemeral type-probe table', {
|
|
142
|
+
tableName: probeName,
|
|
143
|
+
error: err instanceof Error ? err.message : String(err),
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
122
148
|
const out = {
|
|
123
149
|
rowCount: result.rowCount,
|
|
124
|
-
columns:
|
|
150
|
+
columns: typedColumns,
|
|
125
151
|
rows: result.rows,
|
|
126
152
|
};
|
|
127
|
-
if (
|
|
128
|
-
out.dataframe =
|
|
153
|
+
if (userRegisterAs !== undefined)
|
|
154
|
+
out.dataframe = userRegisterAs;
|
|
129
155
|
return out;
|
|
130
156
|
},
|
|
131
157
|
format: (result) => [{ type: 'text', text: renderQuery(result) }],
|
|
132
158
|
});
|
|
159
|
+
/**
|
|
160
|
+
* Build typed column metadata for the response. The handler always runs the
|
|
161
|
+
* query under a `registerAs` (caller-supplied or an internal `_brapi_probe_*`
|
|
162
|
+
* temp name), so DuckDB's `describe()` is the authoritative type source —
|
|
163
|
+
* it preserves BIGINT, DOUBLE, TIMESTAMP, and DECIMAL through the round-trip
|
|
164
|
+
* that JSON serialization would otherwise flatten to VARCHAR. Falls through
|
|
165
|
+
* to row inference only when describe can't see the table (test fakes that
|
|
166
|
+
* don't honor `registerAs`) and finally to UNKNOWN for empty results.
|
|
167
|
+
*/
|
|
168
|
+
async function resolveTypedColumns(bridge, ctx, result, tableName) {
|
|
169
|
+
const tables = await bridge.describe(ctx, { tableName });
|
|
170
|
+
const described = tables[0];
|
|
171
|
+
if (described && described.columns.length > 0) {
|
|
172
|
+
return described.columns.map((c) => ({ name: c.name, type: c.type }));
|
|
173
|
+
}
|
|
174
|
+
if (result.rows.length > 0) {
|
|
175
|
+
const inferred = inferSchemaFromRows(result.rows);
|
|
176
|
+
const byName = new Map(inferred.map((c) => [c.name, c.type]));
|
|
177
|
+
return result.columns.map((name) => ({
|
|
178
|
+
name,
|
|
179
|
+
type: byName.get(name) ?? 'VARCHAR',
|
|
180
|
+
}));
|
|
181
|
+
}
|
|
182
|
+
return result.columns.map((name) => ({ name, type: 'UNKNOWN' }));
|
|
183
|
+
}
|
|
133
184
|
function renderQuery(result) {
|
|
134
185
|
const lines = [];
|
|
135
186
|
const tableHint = result.dataframe ? ` · registered as \`${result.dataframe}\`` : '';
|
|
136
187
|
lines.push(`# ${result.rowCount} row(s)${tableHint}`);
|
|
137
|
-
|
|
188
|
+
const columnList = result.columns.map((c) => `${c.name} (${c.type})`).join(', ');
|
|
189
|
+
lines.push(`- columns: ${columnList}`);
|
|
138
190
|
lines.push(`- returned: ${result.rows.length}`);
|
|
139
191
|
if (result.rows.length === 0) {
|
|
140
192
|
lines.push('');
|
|
@@ -147,11 +199,11 @@ function renderQuery(result) {
|
|
|
147
199
|
lines.push('');
|
|
148
200
|
lines.push(`### Row ${i + 1}`);
|
|
149
201
|
for (const col of result.columns) {
|
|
150
|
-
const value = row[col];
|
|
202
|
+
const value = row[col.name];
|
|
151
203
|
if (value === undefined || value === null)
|
|
152
204
|
continue;
|
|
153
205
|
const rendered = typeof value === 'object' ? JSON.stringify(value) : String(value);
|
|
154
|
-
lines.push(`- **${col}:** ${rendered}`);
|
|
206
|
+
lines.push(`- **${col.name}:** ${rendered}`);
|
|
155
207
|
}
|
|
156
208
|
}
|
|
157
209
|
return lines.join('\n');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"brapi-dataframe-query.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/brapi-dataframe-query.tool.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"brapi-dataframe-query.tool.js","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/brapi-dataframe-query.tool.ts"],"names":[],"mappings":"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"}
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* (operator policy, default 100k, max 500k) so a single query can't trigger
|
|
7
7
|
* unbounded sequential paginated GETs against the upstream BrAPI server.
|
|
8
8
|
* `loadLimit` bounds the rows returned inline; when the pull exceeds
|
|
9
|
-
* loadLimit, the full collected set
|
|
10
|
-
* follow-up.
|
|
9
|
+
* loadLimit, the full collected set is materialized as a dataframe
|
|
10
|
+
* for SQL-based follow-up.
|
|
11
11
|
*
|
|
12
12
|
* @module mcp-server/tools/definitions/brapi-find-genotype-calls.tool
|
|
13
13
|
*/
|
|
@@ -55,16 +55,14 @@ export declare const brapiFindGenotypeCalls: import("@cyanheads/mcp-ts-core").To
|
|
|
55
55
|
variantName: z.ZodRecord<z.ZodString, z.ZodNumber>;
|
|
56
56
|
variantSetDbId: z.ZodRecord<z.ZodString, z.ZodNumber>;
|
|
57
57
|
}, z.core.$strip>;
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
dataframe: z.ZodOptional<z.ZodObject<{
|
|
59
|
+
tableName: z.ZodString;
|
|
60
60
|
rowCount: z.ZodNumber;
|
|
61
|
-
sizeBytes: z.ZodNumber;
|
|
62
61
|
columns: z.ZodArray<z.ZodString>;
|
|
63
62
|
createdAt: z.ZodString;
|
|
64
63
|
expiresAt: z.ZodString;
|
|
65
64
|
truncated: z.ZodOptional<z.ZodBoolean>;
|
|
66
65
|
maxRows: z.ZodOptional<z.ZodNumber>;
|
|
67
|
-
dataframe: z.ZodOptional<z.ZodString>;
|
|
68
66
|
}, z.core.$strip>>;
|
|
69
67
|
truncated: z.ZodBoolean;
|
|
70
68
|
warnings: z.ZodArray<z.ZodString>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"brapi-find-genotype-calls.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAsB,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AA8HjE,eAAO,MAAM,sBAAsB
|
|
1
|
+
{"version":3,"file":"brapi-find-genotype-calls.tool.d.ts","sourceRoot":"","sources":["../../../../src/mcp-server/tools/definitions/brapi-find-genotype-calls.tool.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAsB,CAAC,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AA8HjE,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsNjC,CAAC"}
|