@barivia/barsom-mcp 0.7.13 → 0.7.16
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/README.md +44 -9
- package/dist/index.js +1 -1
- package/dist/prepare_training_prompt.js +16 -0
- package/dist/shared.js +53 -5
- package/dist/tools/explore_map.js +2 -2
- package/dist/tools/guide_barsom.js +2 -2
- package/dist/tools/training_guidance.js +1 -1
- package/dist/tools/training_prep.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# @barivia/barsom-mcp
|
|
2
2
|
|
|
3
|
-
MCP proxy for the Barivia Analytics Engine — connects any stdio MCP client (Cursor, Claude Desktop, etc.) to the barSOM cloud API. **`guide_barsom_workflow`** is the canonical bootstrap: it
|
|
3
|
+
MCP proxy for the Barivia Analytics Engine — connects any stdio MCP client (Cursor, Claude Desktop, etc.) to the barSOM cloud API. The npm package is **`@barivia/barsom-mcp`**; many configs label the server **`analytics-engine`** (the MCP server name in the client JSON). **`guide_barsom_workflow`** is the canonical bootstrap: it loads plan-scoped workflow text from the Barivia API when online (tool map, async rules, training modes, SOP). If the API is unreachable, it returns a short offline stub. Core tools are `datasets`, `jobs` (`train_map`, `train_siom_map`, `train_floop_siom` where entitled; `train_floop_chain` is deprecated), `results`, and `inference`. **Optional MCP App tools** (`training_prep`, `training_monitor`, `results_explorer`) add embedded or localhost viz; they are **not required** to complete upload → train → poll → results.
|
|
4
|
+
|
|
5
|
+
**Pre-training help (pick one):** **`prepare_training`** prompt = narrative checklist (tier-scoped from the API when online); **`training_guidance`** tool = structured presets and parameter hints; **`training_prep`** tool = interactive UI plus **`submit_prepared_training`**.
|
|
4
6
|
|
|
5
7
|
## Installation
|
|
6
8
|
|
|
@@ -38,19 +40,43 @@ MCP clients typically run it with **`npx`** (downloads on first use):
|
|
|
38
40
|
| `BARIVIA_WORKSPACE_ROOT` | No | `process.cwd()` or `PWD` | Directory for relative `file_path` and `save_to_disk`. In Cursor MCP, `process.cwd()` is often the MCP install dir — add `BARIVIA_WORKSPACE_ROOT` to your MCP config `env` with your project path (e.g. `/home/user/myproject`). Absolute paths and `file://` URIs work without it. |
|
|
39
41
|
| `BARIVIA_FETCH_TIMEOUT_MS` | No | `30000` | Per-request HTTP timeout (ms) to the API. Increase (e.g. `120000`) on slow networks or when the API does long-running work. Large dataset uploads use a separate longer timeout internally. |
|
|
40
42
|
| `BARIVIA_VIZ_PORT` | No | OS-assigned | When the client has no MCP Apps support, the proxy may start a local viz server on `127.0.0.1`; set a fixed port if you need stable bookmark URLs. |
|
|
43
|
+
| `BARIVIA_ENFORCE_WORKSPACE_SANDBOX` | No | unset | If `1` or `true`, `datasets(upload)` **file_path** and `file://` paths must resolve under the MCP workspace root (same rule as relative paths). Default allows **absolute** paths anywhere on the machine the client can read — treat that as **high trust** (same API key can already exfiltrate org data via the API). |
|
|
41
44
|
|
|
42
45
|
Legacy `BARSOM_API_KEY` / `BARSOM_API_URL` / `BARSOM_WORKSPACE_ROOT` are also accepted as fallbacks.
|
|
43
46
|
|
|
47
|
+
### Trust model (who are we trusting?)
|
|
48
|
+
|
|
49
|
+
- **API key** — Anyone with your key can access your tenant on the Barivia API like any other HTTP client. The proxy does not add a separate authorization layer.
|
|
50
|
+
- **Local machine** — The process runs with **your** OS user. It can read files you pass as `file_path` (and, by default, **any** absolute path). Prefer `BARIVIA_WORKSPACE_ROOT` + project-relative paths; use **`BARIVIA_ENFORCE_WORKSPACE_SANDBOX=1`** when you want uploads constrained to the workspace.
|
|
51
|
+
- **Logs** — stderr may include API paths and tool activity; do not log secrets in MCP client configs.
|
|
52
|
+
|
|
44
53
|
**Supported stack:** Node **18+** (see `engines` in `package.json`). Built with `@modelcontextprotocol/sdk` **^1.x** — if a major MCP client upgrade breaks tools, check SDK release notes alongside this package version.
|
|
45
54
|
|
|
46
55
|
**Local viz fallback:** If the IDE does not advertise MCP Apps, the proxy starts an HTTP server bound to **127.0.0.1** only (not exposed to the LAN). It serves built-in HTML for training prep / monitor / results explorer and proxies read-only API calls with your existing API key. Responses may include `http://127.0.0.1:<port>/viz/...` links. Browser `Access-Control-Allow-Origin: *` applies only to that localhost origin so the embedded pages can load data.
|
|
47
56
|
|
|
48
|
-
## Tools (
|
|
57
|
+
## Tools and prompts (15 tools + 2 prompts)
|
|
58
|
+
|
|
59
|
+
All multi-action tools follow the `datasets` / `jobs` / `results` / `inference` / `account` pattern: a required `action` enum routes to the correct operation.
|
|
60
|
+
|
|
61
|
+
**Prompts (not tools):** `info` (short orientation; prefer `guide_barsom_workflow` for depth), `prepare_training` (requires `dataset_id`; checklist text from API when online).
|
|
49
62
|
|
|
50
|
-
|
|
63
|
+
### Flattened catalog (optional grouping in UIs)
|
|
64
|
+
|
|
65
|
+
| Section | Items |
|
|
66
|
+
|--------|--------|
|
|
67
|
+
| Bootstrap | `guide_barsom_workflow`, prompts `info`, `prepare_training` |
|
|
68
|
+
| Data | `datasets` |
|
|
69
|
+
| Train & poll | `jobs`, `submit_prepared_training` (after `training_prep`), `training_monitor` (optional) |
|
|
70
|
+
| Results | `results`, `results_explorer` (optional) |
|
|
71
|
+
| Inference | `inference` |
|
|
72
|
+
| Account | `account` |
|
|
73
|
+
| Optional UI | `training_prep`, `training_monitor`, `results_explorer` |
|
|
74
|
+
| Advanced / legacy | `training_guidance`, `explore_map` (deprecated alias) |
|
|
75
|
+
|
|
76
|
+
Agents should not call **`_fetch_figure`** from chat; it exists for the Results Explorer MCP App host. Use `results(action=get)` or `results_explorer` instead.
|
|
51
77
|
|
|
52
78
|
### `guide_barsom_workflow`
|
|
53
|
-
Call at the **start of mapping work** (or when the user asks what the MCP can do).
|
|
79
|
+
Call at the **start of mapping work** (or when the user asks what the MCP can do). Returns plan-scoped orientation from the Barivia API when online. No parameters. **`training_guidance`** returns JSON presets and hints with the same entitlement filtering.
|
|
54
80
|
|
|
55
81
|
### `datasets(action)`
|
|
56
82
|
|
|
@@ -101,7 +127,7 @@ All actions use a frozen trained map — no retraining. Derived columns use **`d
|
|
|
101
127
|
| `enrich` | enriched.csv: training data + bmu_x/y/node_index/cluster_id | 5–60s |
|
|
102
128
|
| `compare` | density-diff heatmap + top gained/lost nodes — drift, A/B, cohort | 30–120s |
|
|
103
129
|
| `project_columns` | Project one or more dataset columns onto the trained map (component planes) | async |
|
|
104
|
-
| `report` |
|
|
130
|
+
| `report` | Report **manifest** (figure names, download URLs, metrics, cluster summary) — sync; use with `results(download)` on the training `job_id` for `report.pdf` when present; build custom PDFs in Quarto/Jupyter | immediate |
|
|
105
131
|
|
|
106
132
|
### `account(action)`
|
|
107
133
|
|
|
@@ -118,14 +144,20 @@ All actions use a frozen trained map — no retraining. Derived columns use **`d
|
|
|
118
144
|
|
|
119
145
|
| Tool | Role |
|
|
120
146
|
|------|------|
|
|
121
|
-
| `training_prep` | Review variables, transforms, hyperparameters before submit
|
|
147
|
+
| `training_prep` | Review variables, transforms, hyperparameters before submit |
|
|
148
|
+
| `submit_prepared_training` | Submit the reviewed prep (`review_token` + `explicit_confirm=true`) |
|
|
122
149
|
| `training_monitor` | Visual progress for a `job_id`; optional — `jobs(action=status)` is enough |
|
|
123
150
|
| `results_explorer` | Browse metrics and figures after training completes |
|
|
124
|
-
| `explore_map` |
|
|
125
|
-
| `_fetch_figure` |
|
|
151
|
+
| `explore_map` | **Deprecated** — alias of `results_explorer`; migrate configs to `results_explorer` |
|
|
152
|
+
| `_fetch_figure` | **Host / App only** — Results Explorer invokes this for one raster figure; not for agent chat |
|
|
126
153
|
|
|
127
154
|
When the client does not advertise MCP Apps support, the proxy starts **`viz-server`** on **`127.0.0.1`** (localhost-only). Tool responses can include `http://127.0.0.1:PORT/viz/...` links. See **Local viz fallback** under Environment Variables.
|
|
128
155
|
|
|
156
|
+
### Migration notes
|
|
157
|
+
|
|
158
|
+
- **`explore_map` → `results_explorer`:** Update Cursor, Claude Desktop, or other MCP configs that still reference `explore_map`. The alias remains for backward compatibility.
|
|
159
|
+
- **Shorter `info` prompt:** Clients that relied on the old long `info` text should use **`guide_barsom_workflow`** or server **instructions** for the full story.
|
|
160
|
+
|
|
129
161
|
### `send_feedback`
|
|
130
162
|
Submit feedback or feature requests (max 1400 characters, ~190 words).
|
|
131
163
|
|
|
@@ -168,8 +200,11 @@ cd apps/mcp-proxy
|
|
|
168
200
|
npm install
|
|
169
201
|
npm run dev # Run with tsx (hot reload)
|
|
170
202
|
npm run build # Compile to dist/
|
|
203
|
+
npm test # Vitest
|
|
171
204
|
```
|
|
172
205
|
|
|
206
|
+
**Post-change spot-check (real MCP client):** confirm `guide_barsom_workflow` appears near the top of the tool list, `explore_map` still works as an alias of `results_explorer`, and Results Explorer can still load figures (it uses `_fetch_figure` internally — agents should rely on `results` / `results_explorer`).
|
|
207
|
+
|
|
173
208
|
For local development against a local API stack:
|
|
174
209
|
|
|
175
210
|
```bash
|
|
@@ -199,7 +234,7 @@ From the platform root:
|
|
|
199
234
|
|
|
200
235
|
```bash
|
|
201
236
|
cd barivia-platform
|
|
202
|
-
bash scripts/check-mcp-proxy-publish.sh
|
|
237
|
+
bash scripts/checks/check-mcp-proxy-publish.sh
|
|
203
238
|
```
|
|
204
239
|
|
|
205
240
|
Compares local `build:publish` output to the tarball on **public npm**. Exit 0 = match; exit 1 = diff. `VERBOSE=1` for a full `dist/` diff.
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{McpServer as e}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as t}from"@modelcontextprotocol/sdk/server/stdio.js";import{z as o}from"zod";import{getUiCapability as a,registerAppResource as i,RESOURCE_MIME_TYPE as r}from"@modelcontextprotocol/ext-apps/server";import{startVizServer as n}from"./viz-server.js";import{API_KEY as s,apiCall as l,apiRawCall as c,loadViewHtml as p,setVizPort as d,setClientSupportsMcpApps as m}from"./shared.js";import{registerDatasetsTool as u}from"./tools/datasets.js";import{registerJobsTool as f,JOBS_DESCRIPTION_BASE as g}from"./tools/jobs.js";import{registerResultsTool as h}from"./tools/results.js";import{registerExploreMapTool as _,RESULTS_EXPLORER_URI as b}from"./tools/explore_map.js";import{registerAccountTool as y}from"./tools/account.js";import{registerInferenceTool as w}from"./tools/inference.js";import{registerGuideBarsomTool as j}from"./tools/guide_barsom.js";import{registerTrainingGuidanceTool as v}from"./tools/training_guidance.js";import{registerFeedbackTool as x}from"./tools/feedback.js";import{registerTrainingPrepTools as I,TRAINING_PREP_URI as k}from"./tools/training_prep.js";import{registerTrainingMonitorTool as M,TRAINING_MONITOR_URI as P}from"./tools/training_monitor.js";s||(console.error("Error: BARIVIA_API_KEY not set. Set it in your MCP client config."),process.exit(1));const O=new e({name:"analytics-engine",version:"0.7.10",instructions:"# Barivia Mapping Analytics Engine\n\nYou have access to a mapping (Self-Organizing Map) analytics platform that projects high-dimensional data onto a 2D grid, revealing clusters, gradients, and anomalies.\n\n## Typical workflow\n\n1. **Upload** → `datasets(action=upload)` — ingest a CSV\n2. **Preview** → `datasets(action=preview)` — inspect columns, detect cyclics/datetimes; add derived columns with `datasets(action=add_expression)` if needed\n3. **Train** → choose one:\n - `jobs(action=train_map, dataset_id=...)` for a standard fixed-grid SOM\n - `jobs(action=train_siom_map, dataset_id=...)` for a fixed-grid SIOM with coverage regularization\n - `jobs(action=train_floop_siom, dataset_id=...)` for FLooP-SIOM when the plan includes all_algorithms (Premium or Enterprise; default topology=free / CHL; optional topology=chain)\n Returns a job_id; poll `jobs(action=status, job_id=...)` until completed\n4. **Analyze** → `results(action=get)` — view metrics and figures (grid-map or FLooP-specific; no separate analyze tool)\n5. **Compare / Export / Inference** → `jobs(action=compare)`, `results(download)`, `inference` (predict/enrich/compare/report)\n\nFor **proxy model, full tool map, async rules, training modes (tier-scoped), and optional MCP App UIs**, call `guide_barsom_workflow` first—it loads the ground-truth bootstrap from the API (`GET /v1/docs/workflow`; this section stays short on purpose).\n\n## Tool categories\n\n| Category | Tools |\n|----------|-------|\n| Data management | `datasets` (upload/preview/list/subset/delete/add_expression) |\n| Jobs & training | `jobs` (train_map/train_siom_map/train_floop_siom/status/list/compare/cancel/delete/batch_predict; deprecated alias train_floop_chain) |\n| Results | `results` (get/recolor/download/export/transition_flow) |\n| Inference & export | `inference` (predict/enrich/compare/report/project_columns) |\n| Account | `account` (status/request_compute/compute_status/release_compute/history/add_funds) |\n| Utility | `guide_barsom_workflow`, `training_guidance`, `training_prep`, `results_explorer`, `training_monitor`, `send_feedback` |\n\n## Optional rich UI (MCP Apps)\n\n**None of these are required** to train, poll, or read results—`jobs` + `results` + text output are enough. **Recommended** for learning: `training_prep` (preparation), `results_explorer` (postprocessing). **Optional:** `training_monitor(job_id)` for visual progress; `jobs(action=status)` is sufficient without it.\n\n## Async job pattern\n\nMost operations are async. Every tool that submits a job either:\n- **Auto-polls** (results(recolor/transition_flow), inference) — waits up to the action-specific timeout then returns or gives a job_id for manual polling\n- **Returns immediately** (jobs(action=train_map/train_siom_map/train_floop_siom)) — always requires manual `jobs(action=status, job_id=...)` polling (`train_floop_chain` is a deprecated alias for `train_floop_siom`)\n\n**Do not tell the user a job failed because it is still running.** If a tool returns a job_id, poll `jobs(action=status)` every 10–15 seconds. Grid-map training takes 30s–10min depending on grid size and dataset; FLooP-SIOM jobs can also take several minutes for larger `max_nodes` or `thorough` runs.\nFor FLooP-SIOM, `max_nodes` is a total node budget, not a grid side length. If omitted, the backend uses a dataset-size heuristic; reduce `max_nodes` before increasing `effort` when coverage looks collapsed.\n\n## Credit and cost\n\nJobs consume compute credits. Inference jobs are priced the same as projection jobs. Check `account(action=status)` to see the remaining balance and queue depth before starting large jobs.\n\n## Key constraints\n\n- For parameter guidance (grid, epochs, presets, when to use standard SOM vs SIOM vs FLooP-SIOM), use `training_guidance` or `prepare_training` — do not guess.\n- Column names are case-sensitive; always match exactly what `datasets(action=preview)` returns\n- Uploads may include text/categorical columns, but the default training path is still numeric/cyclic/temporal. If a categorical column truly matters, use explicit `categorical_features` for simple baseline encoding.\n- `predict` input must match the model's supported inference contract. Numeric/batch predict expects the training feature set; single-row stateless inference can also accept raw categorical strings for baseline `categorical_features` models."});i(O,b,b,{mimeType:r},async()=>{const e=await p("results-explorer");return{contents:[{uri:b,mimeType:r,text:e??"<html><body>Results Explorer view not built yet. Run: npm run build:views</body></html>"}]}}),i(O,k,k,{mimeType:r},async()=>{const e=await p("training-prep");return{contents:[{uri:k,mimeType:r,text:e??"<html><body>Training Preparation view not built yet.</body></html>"}]}}),i(O,P,P,{mimeType:r},async()=>{const e=await p("training-monitor");return{contents:[{uri:P,mimeType:r,text:e??"<html><body>Training Monitor view not built yet.</body></html>"}]}}),_(O),I(O),M(O),j(O),u(O),f(O,g),h(O),y(O),w(O),v(O),x(O),O.prompt("info","Overview of the Barivia Mapping MCP: capabilities, workflow, tools, analysis types, and tips. Use when the user asks what this MCP can do, how to get started, or what the process is.",{},()=>({messages:[{role:"user",content:{type:"text",text:["Inform the user using this overview:","","**What it is:** Barivia MCP connects you to a mapping analytics engine that learns a 2D map from high-dimensional data for visualization, clustering, pattern discovery, and temporal analysis.","","**Orientation:** Call `guide_barsom_workflow` first for proxy model, full tool list, async rules, training modes, and optional MCP App UIs (defer long-form detail there).","","**Core workflow:**","0. **Prepare** — CSV with header; no NaNs in used columns; numeric and datetime columns are the default training path; raw categoricals can stay in the CSV but should usually be excluded unless you explicitly use simple `categorical_features` encoding","1. **Upload** — `datasets(action=upload)` with a CSV file path or inline data","2. **Preview** — `datasets(action=preview)` to inspect columns, stats, and detect cyclic/datetime fields","3. **Prepare** — use the `prepare_training` prompt for a guided checklist (column selection, transforms, cyclic encoding, feature weights, grid sizing)","4. **Train** — choose one: `jobs(action=train_map, dataset_id=...)` for a standard fixed-grid SOM, `jobs(action=train_siom_map, dataset_id=...)` for a fixed-grid SIOM with coverage regularization, or `jobs(action=train_floop_siom, dataset_id=...)` for FLooP-SIOM only on Premium / Enterprise (`all_algorithms`; default topology=free / CHL; optional topology=chain). Use `preset=quick|standard|refined|high_res` for standard or SIOM map defaults","5. **Monitor** — `jobs(action=status, job_id=...)` every 10–15s until complete (required path). Optional: `training_monitor(job_id=...)` for a visual panel—not required.","6. **View and interpret** — `results(action=get)` returns metrics and figures. Grid-map jobs show U-matrix, component planes, and clusters; FLooP-SIOM jobs show structure/coverage, occupation/profile views, and metrics. Optional: `results_explorer(job_id=...)` for interactive browsing; `results(action=get)` alone is enough.","7. **Feedback** — Ask the user if they'd like to submit feedback via `send_feedback` based on their experience.","8. **Iterate** — `results(action=recolor)` to change colormap, `jobs(action=compare)` to compare hyperparameters, `inference(action=project_columns)` to overlay dataset columns onto the map","","All visualizations and metrics come from `results(action=get)`; use figures=all or export_type=... for more.","","**Data tools:**","- `datasets(action=subset)` — filter by row range, value thresholds (gt/lt/gte/lte), equality, or set membership. Combine row_range + filter","- `datasets(action=add_expression)` — create computed columns from expressions (ratios, differences, etc.)","- `inference(action=project_columns)` — overlay one or more dataset columns onto a trained map (component planes)","","**Output options:** Format (png/pdf/svg) and colormap (coolwarm, viridis, plasma, inferno, hsv, twilight, etc.) can be set at training or changed later via results(action=recolor).","","**Key tools:** datasets, jobs (train_map/train_siom_map/train_floop_siom/status/list/...), results, inference (predict/enrich/compare/project_columns/report), account, guide_barsom_workflow, training_guidance, training_prep, results_explorer, training_monitor.","","**Optional rich UI:** `training_prep` and `results_explorer` are recommended for prep and postprocessing; `training_monitor` is optional. None are required—`jobs` + `results` complete the workflow.","","**Tips:**","- For the full step-by-step SOP and capabilities text (from the API, scoped to your plan), use the `guide_barsom_workflow` tool","- Always `datasets(action=preview)` before training to understand your data","- Use `account(action=status)` to check GPU availability, queue depth, and plan limits before large jobs","- Start with `preset=quick` for fast iteration, then `refined` for publication quality","- For time-series data, consider `transition_flow` after training","","Keep the reply scannable with headers and bullet points."].join("\n")}}]})),O.prompt("prepare_training","Guided pre-training checklist. Use after uploading a dataset and before calling jobs(action=train_map), jobs(action=train_siom_map), or jobs(action=train_floop_siom) when entitled. Walks through data inspection, column selection, transforms, cyclic/temporal features, weighting, subsetting, and grid sizing.",{dataset_id:o.string().describe("Dataset ID to prepare for training")},async({dataset_id:e})=>{let t=`Please run datasets(action=preview, dataset_id="${e}") to inspect columns, then datasets(action=analyze, dataset_id="${e}") to see which columns and temporal periods are most informative. Then choose the training path: jobs(action=train_map, dataset_id="${e}", ...) for a standard fixed-grid SOM, jobs(action=train_siom_map, dataset_id="${e}", ...) for a fixed-grid SIOM, or jobs(action=train_floop_siom, dataset_id="${e}", ...) for FLooP-SIOM (default topology=free / CHL; optional topology=chain).`;try{const o=await l("GET",`/v1/docs/prepare_training?dataset_id=${e}`);o.prompt&&(t=o.prompt)}catch(e){}return{messages:[{role:"user",content:{type:"text",text:t}}]}});const C=new t;(async function(){try{const e=await n(l,c,p);d(e)}catch(e){process.env.BARIVIA_VIZ_PORT&&console.error("Barivia viz server failed to start:",e)}const e=O.server;e.oninitialized=()=>{const t=e.getClientCapabilities(),o=a(t);m(!!o?.mimeTypes?.includes(r))},await O.connect(C)})().catch(console.error);
|
|
2
|
+
import{McpServer as e}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as t}from"@modelcontextprotocol/sdk/server/stdio.js";import{z as o}from"zod";import{getUiCapability as r,registerAppResource as n,RESOURCE_MIME_TYPE as s}from"@modelcontextprotocol/ext-apps/server";import{startVizServer as i}from"./viz-server.js";import{API_KEY as a,apiCall as l,apiRawCall as p,loadViewHtml as c,setVizPort as m,setClientSupportsMcpApps as d}from"./shared.js";import{registerDatasetsTool as u}from"./tools/datasets.js";import{registerJobsTool as f,JOBS_DESCRIPTION_BASE as _}from"./tools/jobs.js";import{registerResultsTool as g}from"./tools/results.js";import{registerExploreMapTool as h,RESULTS_EXPLORER_URI as b}from"./tools/explore_map.js";import{registerAccountTool as y}from"./tools/account.js";import{registerInferenceTool as w}from"./tools/inference.js";import{registerGuideBarsomTool as j}from"./tools/guide_barsom.js";import{registerTrainingGuidanceTool as v}from"./tools/training_guidance.js";import{registerFeedbackTool as x}from"./tools/feedback.js";import{registerTrainingPrepTools as P,TRAINING_PREP_URI as I}from"./tools/training_prep.js";import{registerTrainingMonitorTool as k,TRAINING_MONITOR_URI as A}from"./tools/training_monitor.js";import{resolvePrepareTrainingPromptText as T}from"./prepare_training_prompt.js";a||(console.error("Error: BARIVIA_API_KEY not set. Set it in your MCP client config."),process.exit(1));const C=new e({name:"analytics-engine",version:"0.7.16",instructions:"# Barivia Mapping Analytics Engine\n\nSelf-organizing map (SOM) analytics: project high-dimensional data to a 2D grid for clusters, gradients, and anomalies.\n\n## Workflow (short)\n\nUpload (`datasets(upload)`) → `datasets(preview)` and `datasets(analyze)` before train → submit one of `jobs(train_map)`, `jobs(train_siom_map)`, or `jobs(train_floop_siom)` (only if plan allows FLooP) → poll `jobs(status)` every 10–15s until `completed` → `results(get)` for metrics and figures (there is no separate analyze tool). Then `jobs(compare)`, `results(download/recolor/transition_flow)`, or `inference` as needed.\n\n**Full detail:** Call `guide_barsom_workflow` for plan-scoped tool map, training modes, async rules, optional MCP App UIs, and step-by-step SOP (from the Barivia API when online).\n\n## Tool map (compact)\n\n| Area | Tool | Notes |\n|------|------|--------|\n| Data | `datasets` | upload, preview, analyze, list, subset, add_expression, delete |\n| Jobs | `jobs` | train_map, train_siom_map, train_floop_siom (entitled), status, list, compare, cancel, delete, batch_predict, run_baseline_study; `train_floop_chain` = deprecated alias for train_floop_siom |\n| Results | `results` | get, export, download, recolor (async), transition_flow (async; time-ordered rows only) |\n| Inference | `inference` | predict, enrich, compare, project_columns, report |\n| Account | `account` | status, burst/compute actions, history, add_funds |\n| Bootstrap | `guide_barsom_workflow` | orientation + SOP |\n| Parameters | `training_guidance` | presets and field hints (API-scoped) |\n| Prep | `prepare_training` prompt, `training_prep` + `submit_prepared_training` | checklist / interactive UI |\n| Explore | `results_explorer`, `training_monitor` | optional MCP Apps; `explore_map` = deprecated alias of `results_explorer`; `jobs(status)` and `results(get)` suffice without them |\n| Other | `send_feedback` | only after user agrees |\n\n## Async pattern\n\n- **Manual poll:** Training submits return `job_id` immediately — poll `jobs(status)` every 10–15s. **Running is not failed**; large grids or FLooP-SIOM can take many minutes. `max_nodes` (FLooP) is a total node budget, not grid side length.\n- **Often auto-polled:** `inference` actions, `results(recolor)`, `results(transition_flow)` may wait in-proxy; if you get a `job_id`, poll `jobs(status)` the same way.\n\nCredits: jobs consume compute credits; check `account(status)` before big runs. Slow networks: users can raise `BARIVIA_FETCH_TIMEOUT_MS`.\n\n## Constraints\n\n- Prep ladder: `prepare_training` prompt = narrative checklist; `training_guidance` = structured hints; `training_prep` = UI + guarded submit. Do not guess tiers or FLooP entitlement.\n- Column names are case-sensitive — match `datasets(preview)`.\n- Default training path is numeric/cyclic/temporal; use explicit `categorical_features` for baseline categoricals. `predict` must match the model contract.\n- After `recolor`, `transition_flow`, or `project_columns`, use the **new** `job_id` returned for follow-up `results` if applicable."});n(C,b,b,{mimeType:s},async()=>{const e=await c("results-explorer");return{contents:[{uri:b,mimeType:s,text:e??"<html><body>Results Explorer view not built yet. Run: npm run build:views</body></html>"}]}}),n(C,I,I,{mimeType:s},async()=>{const e=await c("training-prep");return{contents:[{uri:I,mimeType:s,text:e??"<html><body>Training Preparation view not built yet.</body></html>"}]}}),n(C,A,A,{mimeType:s},async()=>{const e=await c("training-monitor");return{contents:[{uri:A,mimeType:s,text:e??"<html><body>Training Monitor view not built yet.</body></html>"}]}}),j(C),h(C),P(C),k(C),u(C),f(C,_),g(C),y(C),w(C),v(C),x(C),C.prompt("info","Short orientation for the Barivia Mapping MCP. For full plan-scoped workflow, tool map, and SOP, the model should call guide_barsom_workflow. Use when the user asks what this MCP can do or how to get started.",{},()=>({messages:[{role:"user",content:{type:"text",text:["Give a concise, scannable answer (headers + bullets):","","**What it is:** MCP client to the Barivia mapping engine (2D SOM / SIOM / FLooP-SIOM when entitled) over HTTPS.","","**First step:** Call `guide_barsom_workflow` for plan-scoped bootstrap (full tool list, async rules, training modes, optional MCP Apps, SOP).","","**Core path:** `datasets(upload)` → `datasets(preview)` + `datasets(analyze)` → choose training action → poll `jobs(status)` every 10–15s until completed → `results(get)` (all main figures/metrics; no separate analyze tool).","","**Key tools:** `datasets` (data), `jobs` (train/poll/compare/…), `results` (get/download/export/recolor/transition_flow), `inference` (predict/enrich/compare/project_columns/report), `account` (status/credits/queue).","","**Prep help:** `prepare_training` prompt (checklist) · `training_guidance` (presets/JSON hints) · `training_prep` + `submit_prepared_training` (interactive UI).","","**Optional UI:** `results_explorer`, `training_monitor` — nice for browsing; not required if you use `results` + `jobs(status)`.","","**After training:** `jobs(compare)` across runs, `results(recolor)`, `inference(project_columns)` for variables not in training, `transition_flow` only if rows are time-ordered.","","**Rules:** Running ≠ failed. Column names must match `datasets(preview)` exactly. Do not call `_fetch_figure` from chat (host/UI only); use `results(get)` or `results_explorer`.","","Offer `send_feedback` only after asking the user."].join("\n")}}]})),C.prompt("prepare_training","Narrative pre-training checklist (prompt). Use after upload and before train. Content is tier-scoped from the API when online. Prep ladder: this prompt = story checklist; training_guidance tool = JSON presets/parameter hints; training_prep tool = interactive UI + submit_prepared_training.",{dataset_id:o.string().describe("Dataset ID to prepare for training")},async({dataset_id:e})=>({messages:[{role:"user",content:{type:"text",text:await T(e)}}]}));const M=new t;(async function(){try{const e=await i(l,p,c);m(e)}catch(e){process.env.BARIVIA_VIZ_PORT&&console.error("Barivia viz server failed to start:",e)}const e=C.server;e.oninitialized=()=>{const t=e.getClientCapabilities(),o=r(t);d(!!o?.mimeTypes?.includes(s))},await C.connect(M)})().catch(console.error);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { apiCall } from "./shared.js";
|
|
2
|
+
const FALLBACK_PREFIX = "Please run datasets(action=preview, dataset_id=\"{id}\") to inspect columns, then datasets(action=analyze, dataset_id=\"{id}\") to see which columns and temporal periods are most informative. Then choose the training path: jobs(action=train_map, dataset_id=\"{id}\", ...) for a standard fixed-grid SOM, jobs(action=train_siom_map, dataset_id=\"{id}\", ...) for a fixed-grid SIOM, or jobs(action=train_floop_siom, dataset_id=\"{id}\", ...) for FLooP-SIOM (default topology=free / CHL; optional topology=chain).";
|
|
3
|
+
/** Used by the `prepare_training` MCP prompt; prefers tier-scoped text from the API when online. */
|
|
4
|
+
export async function resolvePrepareTrainingPromptText(datasetId) {
|
|
5
|
+
let promptText = FALLBACK_PREFIX.replaceAll("{id}", datasetId);
|
|
6
|
+
try {
|
|
7
|
+
const data = (await apiCall("GET", `/v1/docs/prepare_training?dataset_id=${datasetId}`));
|
|
8
|
+
if (typeof data.prompt === "string" && data.prompt.trim()) {
|
|
9
|
+
promptText = data.prompt.trim();
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
catch {
|
|
13
|
+
// fallback
|
|
14
|
+
}
|
|
15
|
+
return promptText;
|
|
16
|
+
}
|
package/dist/shared.js
CHANGED
|
@@ -104,10 +104,15 @@ export function sandboxPath(userPath, root) {
|
|
|
104
104
|
}
|
|
105
105
|
return resolved;
|
|
106
106
|
}
|
|
107
|
+
function enforceWorkspaceSandboxUpload() {
|
|
108
|
+
const v = process.env.BARIVIA_ENFORCE_WORKSPACE_SANDBOX ?? "";
|
|
109
|
+
return v === "1" || v.toLowerCase() === "true";
|
|
110
|
+
}
|
|
107
111
|
/**
|
|
108
112
|
* Resolves file_path for dataset upload. Security: auth before read, generic errors, reject "..".
|
|
109
113
|
* Accepts: absolute paths, file:// URIs, relative paths (resolved against workspace root).
|
|
110
114
|
* Pre-security-patch behavior: absolute paths worked without BARIVIA_WORKSPACE_ROOT.
|
|
115
|
+
* Set BARIVIA_ENFORCE_WORKSPACE_SANDBOX=1 to require absolute paths to lie under the resolved workspace root.
|
|
111
116
|
*/
|
|
112
117
|
export async function resolveFilePathForUpload(filePath, mcpServer) {
|
|
113
118
|
const trimmed = filePath.trim();
|
|
@@ -120,15 +125,52 @@ export async function resolveFilePathForUpload(filePath, mcpServer) {
|
|
|
120
125
|
if (url.protocol !== "file:" || (url.hostname && url.hostname !== "localhost")) {
|
|
121
126
|
throw new Error("Only local file:// URIs are allowed (no remote hosts).");
|
|
122
127
|
}
|
|
123
|
-
|
|
128
|
+
const p = fileURLToPath(trimmed);
|
|
129
|
+
if (enforceWorkspaceSandboxUpload()) {
|
|
130
|
+
const root = await getWorkspaceRootAsync(mcpServer);
|
|
131
|
+
const real = await fs.realpath(p);
|
|
132
|
+
const realRoot = await fs.realpath(root);
|
|
133
|
+
if (real !== realRoot && !real.startsWith(realRoot + path.sep)) {
|
|
134
|
+
throw new Error(`file:// paths outside the workspace are disabled (BARIVIA_ENFORCE_WORKSPACE_SANDBOX). Workspace: ${realRoot}`);
|
|
135
|
+
}
|
|
136
|
+
const stat = await fs.stat(real);
|
|
137
|
+
if (!stat.isFile()) {
|
|
138
|
+
throw new Error("Path must be a regular file, not a directory.");
|
|
139
|
+
}
|
|
140
|
+
return real;
|
|
141
|
+
}
|
|
142
|
+
return p;
|
|
124
143
|
}
|
|
125
144
|
catch (err) {
|
|
126
145
|
if (err instanceof Error && err.message.includes("remote hosts"))
|
|
127
146
|
throw err;
|
|
147
|
+
if (err instanceof Error && err.message.includes("BARIVIA_ENFORCE_WORKSPACE_SANDBOX"))
|
|
148
|
+
throw err;
|
|
149
|
+
if (err instanceof Error && err.message.includes("regular file"))
|
|
150
|
+
throw err;
|
|
128
151
|
throw new Error("Invalid file:// URI. Use a path like file:///path/to/your/file.csv");
|
|
129
152
|
}
|
|
130
153
|
}
|
|
131
154
|
if (path.isAbsolute(trimmed)) {
|
|
155
|
+
if (enforceWorkspaceSandboxUpload()) {
|
|
156
|
+
const root = await getWorkspaceRootAsync(mcpServer);
|
|
157
|
+
let real;
|
|
158
|
+
try {
|
|
159
|
+
real = await fs.realpath(trimmed);
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
throw new Error(`File not accessible at absolute path. With BARIVIA_ENFORCE_WORKSPACE_SANDBOX, use a path under the workspace root (${root}).`);
|
|
163
|
+
}
|
|
164
|
+
const realRoot = await fs.realpath(root);
|
|
165
|
+
if (real !== realRoot && !real.startsWith(realRoot + path.sep)) {
|
|
166
|
+
throw new Error(`Absolute paths outside the workspace are disabled (BARIVIA_ENFORCE_WORKSPACE_SANDBOX). Workspace root: ${realRoot}`);
|
|
167
|
+
}
|
|
168
|
+
const stat = await fs.stat(real);
|
|
169
|
+
if (!stat.isFile()) {
|
|
170
|
+
throw new Error("Path must be a regular file, not a directory.");
|
|
171
|
+
}
|
|
172
|
+
return real;
|
|
173
|
+
}
|
|
132
174
|
return trimmed;
|
|
133
175
|
}
|
|
134
176
|
const root = await getWorkspaceRootAsync(mcpServer);
|
|
@@ -183,10 +225,16 @@ export function formatApiErrorMessage(status, bodyText, requestId) {
|
|
|
183
225
|
: status === 409
|
|
184
226
|
? " The job may not be in the expected state."
|
|
185
227
|
: status === 429
|
|
186
|
-
? "
|
|
187
|
-
: status
|
|
188
|
-
? "
|
|
189
|
-
:
|
|
228
|
+
? " Plan limit (e.g. dataset cap) or rate limit — read the error above; delete unused datasets or wait and retry."
|
|
229
|
+
: status === 502
|
|
230
|
+
? " Object storage (R2/S3) error from API — retry later."
|
|
231
|
+
: status === 503
|
|
232
|
+
? parsed?.error_code === "system_info_unavailable"
|
|
233
|
+
? " System info (plan/queue) temporarily unavailable — retry later."
|
|
234
|
+
: " API or database temporarily unavailable — retry later."
|
|
235
|
+
: status >= 500
|
|
236
|
+
? " Server error — retry later."
|
|
237
|
+
: "";
|
|
190
238
|
const rid = ` (request id: ${requestId} — include if contacting support)`;
|
|
191
239
|
return `${detail}${code}${hint}${rid}`;
|
|
192
240
|
}
|
|
@@ -168,9 +168,9 @@ export function registerExploreMapTool(server) {
|
|
|
168
168
|
registerAppTool(server, "explore_map", {
|
|
169
169
|
...toolConfig,
|
|
170
170
|
title: "Results Explorer",
|
|
171
|
-
description: `${toolConfig.description}
|
|
171
|
+
description: `${toolConfig.description} Deprecated alias for results_explorer — migrate configs to results_explorer.`,
|
|
172
172
|
}, async ({ job_id }) => handleResultsExplorer(job_id));
|
|
173
|
-
server.tool("_fetch_figure", "
|
|
173
|
+
server.tool("_fetch_figure", "Host / MCP App use only — do NOT invoke from agent chat. Results Explorer calls this to load one raster figure as base64; agents should use results(action=get) or results_explorer instead.", {
|
|
174
174
|
job_id: z.string(),
|
|
175
175
|
filename: z.string(),
|
|
176
176
|
}, async ({ job_id, filename }) => {
|
|
@@ -8,10 +8,10 @@ Configure \`BARIVIA_API_KEY\` and optional \`BARIVIA_API_URL\`, then call **guid
|
|
|
8
8
|
|
|
9
9
|
**Parameter hints:** call \`training_guidance\` (also API-scoped). **Async:** poll \`jobs(action=status)\` every 10–15s after submit.`;
|
|
10
10
|
export function registerGuideBarsomTool(server) {
|
|
11
|
-
server.tool("guide_barsom_workflow", "
|
|
11
|
+
server.tool("guide_barsom_workflow", "Plan-scoped orientation: proxy model, tool categories, async rules, training modes, and step-by-step SOP — loaded from the Barivia API when online. Call at the start of mapping work. Offline: short stub. For field-level parameters, use training_guidance; for a narrative pre-train checklist, use the prepare_training prompt or training_prep.", {}, async () => {
|
|
12
12
|
const md = await fetchWorkflowGuideFromApi();
|
|
13
13
|
if (md) {
|
|
14
|
-
const text = "
|
|
14
|
+
const text = "Plan-scoped workflow (from Barivia API). Text below reflects your API key / plan.\n\n" + md;
|
|
15
15
|
return { content: [{ type: "text", text }] };
|
|
16
16
|
}
|
|
17
17
|
return { content: [{ type: "text", text: OFFLINE_STUB }] };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { fetchTrainingGuidanceFromApi } from "../shared.js";
|
|
2
2
|
export function registerTrainingGuidanceTool(server) {
|
|
3
|
-
server.tool("training_guidance", "
|
|
3
|
+
server.tool("training_guidance", "Structured parameter guidance for training (presets, grid/epochs/batch, model, periodic, SIOM/FLooP fields where your plan allows, categorical baselines). Served from the API and filtered to allowed_job_types. Prep ladder: prepare_training prompt = narrative checklist; this tool = JSON/hints; training_prep = interactive UI + submit_prepared_training. For full orientation and SOP, call guide_barsom_workflow first. Optional UIs: training_prep, results_explorer—not required; jobs + results suffice.", {}, async () => {
|
|
4
4
|
const text = await fetchTrainingGuidanceFromApi();
|
|
5
5
|
return { content: [{ type: "text", text }] };
|
|
6
6
|
});
|
|
@@ -321,7 +321,7 @@ export function registerTrainingPrepTools(server) {
|
|
|
321
321
|
};
|
|
322
322
|
registerAppTool(server, "training_prep", {
|
|
323
323
|
title: "Training Preparation",
|
|
324
|
-
description: "
|
|
324
|
+
description: "Interactive training prep UI + guarded submit (submit_prepared_training). Prep ladder: prepare_training prompt = narrative checklist; training_guidance tool = JSON/presets; this tool = visual review. Opens inline review of variables, transforms, encodings, and hyperparameters.",
|
|
325
325
|
inputSchema: trainPrepSchema,
|
|
326
326
|
_meta: { ui: { resourceUri: TRAINING_PREP_URI } },
|
|
327
327
|
}, async ({ dataset_id, ...args }) => {
|