@barivia/barsom-mcp 0.7.6 → 0.7.12
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 +36 -11
- package/dist/index.js +1 -1
- package/dist/shared.js +105 -31
- package/dist/tools/account.js +0 -1
- package/dist/tools/datasets.js +3 -4
- package/dist/tools/explore_map.js +0 -1
- package/dist/tools/feedback.js +0 -1
- package/dist/tools/guide_barsom.js +13 -70
- package/dist/tools/inference.js +0 -1
- package/dist/tools/jobs.js +2 -3
- package/dist/tools/results.js +0 -1
- package/dist/tools/training_guidance.js +1 -2
- package/dist/tools/training_monitor.js +0 -1
- package/dist/tools/training_prep.js +0 -1
- package/dist/tools/training_review_store.js +0 -1
- package/dist/viz-server.js +0 -1
- package/package.json +10 -4
- package/dist/index.d.ts +0 -25
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/shared.d.ts +0 -176
- package/dist/shared.d.ts.map +0 -1
- package/dist/shared.js.map +0 -1
- package/dist/tools/account.d.ts +0 -3
- package/dist/tools/account.d.ts.map +0 -1
- package/dist/tools/account.js.map +0 -1
- package/dist/tools/datasets.d.ts +0 -11
- package/dist/tools/datasets.d.ts.map +0 -1
- package/dist/tools/datasets.js.map +0 -1
- package/dist/tools/explore_map.d.ts +0 -5
- package/dist/tools/explore_map.d.ts.map +0 -1
- package/dist/tools/explore_map.js.map +0 -1
- package/dist/tools/feedback.d.ts +0 -3
- package/dist/tools/feedback.d.ts.map +0 -1
- package/dist/tools/feedback.js.map +0 -1
- package/dist/tools/guide_barsom.d.ts +0 -3
- package/dist/tools/guide_barsom.d.ts.map +0 -1
- package/dist/tools/guide_barsom.js.map +0 -1
- package/dist/tools/inference.d.ts +0 -3
- package/dist/tools/inference.d.ts.map +0 -1
- package/dist/tools/inference.js.map +0 -1
- package/dist/tools/jobs.d.ts +0 -65
- package/dist/tools/jobs.d.ts.map +0 -1
- package/dist/tools/jobs.js.map +0 -1
- package/dist/tools/results.d.ts +0 -11
- package/dist/tools/results.d.ts.map +0 -1
- package/dist/tools/results.js.map +0 -1
- package/dist/tools/training_guidance.d.ts +0 -3
- package/dist/tools/training_guidance.d.ts.map +0 -1
- package/dist/tools/training_guidance.js.map +0 -1
- package/dist/tools/training_monitor.d.ts +0 -8
- package/dist/tools/training_monitor.d.ts.map +0 -1
- package/dist/tools/training_monitor.js.map +0 -1
- package/dist/tools/training_prep.d.ts +0 -4
- package/dist/tools/training_prep.d.ts.map +0 -1
- package/dist/tools/training_prep.js.map +0 -1
- package/dist/tools/training_review_store.d.ts +0 -17
- package/dist/tools/training_review_store.d.ts.map +0 -1
- package/dist/tools/training_review_store.js.map +0 -1
- package/dist/views/src/views/data-preview/index.html +0 -148
- package/dist/views/src/views/map-explorer/index.html +0 -288
- package/dist/views/src/views/som-explorer/index.html +0 -288
- package/dist/viz-server.d.ts +0 -16
- package/dist/viz-server.d.ts.map +0 -1
- package/dist/viz-server.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
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 returns
|
|
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 fetches **`GET /v1/docs/workflow`** (authenticated) and returns tier-scoped text — proxy model, tool map, async rules, training modes allowed for your key, and step-by-step 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` / `explore_map`) add embedded or localhost viz; they are **not required** to complete upload → train → poll → results.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
|
-
No
|
|
7
|
+
Published on the **public npm registry** as **`@barivia/barsom-mcp`**. No GitHub token or scoped `.npmrc` is required for installs.
|
|
8
|
+
|
|
9
|
+
MCP clients typically run it with **`npx`** (downloads on first use):
|
|
8
10
|
|
|
9
11
|
```json
|
|
10
12
|
{
|
|
@@ -21,7 +23,11 @@ No install step needed. MCP clients run it via `npx`:
|
|
|
21
23
|
}
|
|
22
24
|
```
|
|
23
25
|
|
|
24
|
-
|
|
26
|
+
**Verify:** `npm view @barivia/barsom-mcp version`
|
|
27
|
+
|
|
28
|
+
**Also available:** hosted HTTP MCP at **`https://mcp.barivia.se/mcp`** (same API key; no npm) for clients that support remote MCP.
|
|
29
|
+
|
|
30
|
+
**Future:** A **private npm org** scoped package is an option later (paid npm teams/orgs; users authenticate with npm, usually simpler than GitHub Packages for pure npm consumers).
|
|
25
31
|
|
|
26
32
|
## Environment Variables
|
|
27
33
|
|
|
@@ -30,15 +36,21 @@ This is the standard pattern for MCP servers distributed as npm packages (same a
|
|
|
30
36
|
| `BARIVIA_API_KEY` | Yes | -- | API key (starts with `bv_`) |
|
|
31
37
|
| `BARIVIA_API_URL` | No | `https://api.barivia.se` | API base URL |
|
|
32
38
|
| `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
|
+
| `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
|
+
| `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. |
|
|
33
41
|
|
|
34
42
|
Legacy `BARSOM_API_KEY` / `BARSOM_API_URL` / `BARSOM_WORKSPACE_ROOT` are also accepted as fallbacks.
|
|
35
43
|
|
|
44
|
+
**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
|
+
|
|
46
|
+
**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
|
+
|
|
36
48
|
## Tools (14 registrations)
|
|
37
49
|
|
|
38
50
|
All multi-action tools follow the `datasets` pattern: a required `action` enum routes to the correct operation.
|
|
39
51
|
|
|
40
52
|
### `guide_barsom_workflow`
|
|
41
|
-
Call at the **start of mapping work** (or when the user asks what the MCP can do).
|
|
53
|
+
Call at the **start of mapping work** (or when the user asks what the MCP can do). Loads full orientation from the API (`GET /v1/docs/workflow`); content reflects **your plan** (`allowed_job_types`). No parameters. **`training_guidance`** uses `GET /v1/training/config` with the same entitlement filtering.
|
|
42
54
|
|
|
43
55
|
### `datasets(action)`
|
|
44
56
|
|
|
@@ -112,7 +124,7 @@ All actions use a frozen trained map — no retraining. Derived columns use **`d
|
|
|
112
124
|
| `explore_map` | Legacy alias of `results_explorer` |
|
|
113
125
|
| `_fetch_figure` | Internal helper for Results Explorer (single figure as image) |
|
|
114
126
|
|
|
115
|
-
When the client does not advertise MCP Apps support, the proxy starts **`viz-server`** on
|
|
127
|
+
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.
|
|
116
128
|
|
|
117
129
|
### `send_feedback`
|
|
118
130
|
Submit feedback or feature requests (max 1400 characters, ~190 words).
|
|
@@ -138,6 +150,17 @@ The proxy implements the MCP stdio transport locally and translates tool calls i
|
|
|
138
150
|
MCP Client (Cursor/Claude) ←stdio→ @barivia/barsom-mcp ←HTTPS→ api.barivia.se
|
|
139
151
|
```
|
|
140
152
|
|
|
153
|
+
## Troubleshooting
|
|
154
|
+
|
|
155
|
+
| Symptom | What to check |
|
|
156
|
+
|--------|----------------|
|
|
157
|
+
| `401` / invalid key | `BARIVIA_API_KEY` in MCP config; regenerate or verify at [barivia.se](https://barivia.se). Error text includes a **request id** for support. |
|
|
158
|
+
| Request timed out | Raise `BARIVIA_FETCH_TIMEOUT_MS` (e.g. `120000`). Large uploads already use an extended timeout. |
|
|
159
|
+
| `Path must be within the workspace` / upload can’t find file | Set `BARIVIA_WORKSPACE_ROOT` to your project directory, or use an absolute path / `file:///...` URI. |
|
|
160
|
+
| Job stuck “running” | Poll `jobs(action=status)` every 10–15s; large grids or FLooP-SIOM can take several minutes—not an MCP error. |
|
|
161
|
+
| `429` | Rate limit—wait and retry. |
|
|
162
|
+
| Malformed MCP / client errors | Ensure nothing writes to **stdout** except MCP JSON-RPC (the proxy logs API traffic to **stderr** only). |
|
|
163
|
+
|
|
141
164
|
## Development
|
|
142
165
|
|
|
143
166
|
```bash
|
|
@@ -155,22 +178,24 @@ BARIVIA_API_URL=http://localhost:8080 BARIVIA_API_KEY=bv_test_key npm run dev
|
|
|
155
178
|
|
|
156
179
|
## Publishing
|
|
157
180
|
|
|
158
|
-
|
|
181
|
+
The npm tarball is **runtime-only**: minified `dist/**/*.js`, the three embedded view HTML files, plus `package.json` and `README.md`. It does **not** include TypeScript source, `.map`, `.d.ts`, tests, or `src/`. CI runs `build:publish` (clean `dist`, compile without source maps, views, minify entrypoint) via `prepublishOnly`.
|
|
182
|
+
|
|
183
|
+
Published to **registry.npmjs.org** via GitHub Actions when you push tag `mcp-proxy-v*` (version in `package.json` must match the tag, e.g. tag `mcp-proxy-v0.7.10` for version `0.7.10`):
|
|
159
184
|
|
|
160
185
|
```bash
|
|
161
|
-
git tag mcp-proxy-v0.
|
|
162
|
-
git push origin mcp-proxy-v0.
|
|
186
|
+
git tag mcp-proxy-v0.7.10
|
|
187
|
+
git push origin mcp-proxy-v0.7.10
|
|
163
188
|
```
|
|
164
189
|
|
|
165
|
-
|
|
190
|
+
The repository needs a **`NPM_TOKEN`** secret (npm automation/publish token with access to the `@barivia` scope).
|
|
166
191
|
|
|
167
192
|
### Checking local vs published
|
|
168
193
|
|
|
169
|
-
From the platform root
|
|
194
|
+
From the platform root:
|
|
170
195
|
|
|
171
196
|
```bash
|
|
172
197
|
cd barivia-platform
|
|
173
198
|
bash scripts/check-mcp-proxy-publish.sh
|
|
174
199
|
```
|
|
175
200
|
|
|
176
|
-
|
|
201
|
+
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 c,apiRawCall as l,loadViewHtml as p,setVizPort as d,setClientSupportsMcpApps as m}from"./shared.js";import{registerDatasetsTool as u}from"./tools/datasets.js";import{registerJobsTool as g,JOBS_DESCRIPTION_BASE as f}from"./tools/jobs.js";import{registerResultsTool as _}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 I,TRAINING_PREP_URI as k}from"./tools/training_prep.js";import{registerTrainingMonitorTool as M,TRAINING_MONITOR_URI as O}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 P=new e({name:"analytics-engine",version:"0.7.6",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 (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, and optional MCP App UIs**, call `guide_barsom_workflow` first—it is the ground-truth bootstrap (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(P,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(P,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(P,O,O,{mimeType:r},async()=>{const e=await p("training-monitor");return{contents:[{uri:O,mimeType:r,text:e??"<html><body>Training Monitor view not built yet.</body></html>"}]}}),h(P),I(P),M(P),j(P),u(P),g(P,f),_(P),y(P),w(P),v(P),x(P),P.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 (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, 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")}}]})),P.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). 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 c("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(c,l,p);d(e)}catch(e){process.env.BARIVIA_VIZ_PORT&&console.error("Barivia viz server failed to start:",e)}const e=P.server;e.oninitialized=()=>{const t=e.getClientCapabilities(),o=a(t);m(!!o?.mimeTypes?.includes(r))},await P.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 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);
|
package/dist/shared.js
CHANGED
|
@@ -14,6 +14,12 @@ export const API_KEY = process.env.BARIVIA_API_KEY ?? process.env.BARSOM_API_KEY
|
|
|
14
14
|
export const FETCH_TIMEOUT_MS = parseInt(process.env.BARIVIA_FETCH_TIMEOUT_MS ?? "30000", 10);
|
|
15
15
|
export const MAX_RETRIES = 2;
|
|
16
16
|
export const RETRYABLE_STATUS = new Set([502, 503, 504]);
|
|
17
|
+
/** User-facing links; keep aligned with barivia.se / api.barivia.se. */
|
|
18
|
+
export const PUBLIC_SITE_ORIGIN = "https://barivia.se";
|
|
19
|
+
/** Poll window for datasets(add_expression) / derive jobs (server-side work can exceed 30s). */
|
|
20
|
+
export const POLL_DERIVE_MAX_MS = 120_000;
|
|
21
|
+
/** Large CSV uploads may exceed default FETCH_TIMEOUT_MS. */
|
|
22
|
+
export const UPLOAD_DATASET_TIMEOUT_MS = 180_000;
|
|
17
23
|
// ---------------------------------------------------------------------------
|
|
18
24
|
// Shared state (mutable)
|
|
19
25
|
// ---------------------------------------------------------------------------
|
|
@@ -149,10 +155,50 @@ export async function resolveFilePathForUpload(filePath, mcpServer) {
|
|
|
149
155
|
throw new Error(`File not accessible. For relative paths, set BARIVIA_WORKSPACE_ROOT in your MCP config. Or use an absolute path or file:// URI.`);
|
|
150
156
|
}
|
|
151
157
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
158
|
+
/** User-visible API error line (includes request id for support). Exported for tests. */
|
|
159
|
+
export function formatApiErrorMessage(status, bodyText, requestId) {
|
|
160
|
+
let parsed = null;
|
|
161
|
+
try {
|
|
162
|
+
const j = JSON.parse(bodyText);
|
|
163
|
+
if (j && typeof j === "object")
|
|
164
|
+
parsed = j;
|
|
165
|
+
}
|
|
166
|
+
catch {
|
|
167
|
+
/* ignore */
|
|
168
|
+
}
|
|
169
|
+
const detail = (parsed?.error != null && String(parsed.error)) ||
|
|
170
|
+
(bodyText.trim() ? bodyText.trim() : `HTTP ${status}`);
|
|
171
|
+
const code = parsed?.error_code != null ? ` (error_code: ${parsed.error_code})` : "";
|
|
172
|
+
const accountHint = ` Regenerate or verify your key via ${PUBLIC_SITE_ORIGIN} if needed.`;
|
|
173
|
+
const hint = status === 400
|
|
174
|
+
? " Check parameter types and required fields."
|
|
175
|
+
: status === 401
|
|
176
|
+
? ` Check BARIVIA_API_KEY in your MCP config.${accountHint}`
|
|
177
|
+
: status === 403
|
|
178
|
+
? ` Access denied for this operation (plan or permissions).${accountHint}`
|
|
179
|
+
: status === 402
|
|
180
|
+
? ` Credits or subscription may be insufficient — see ${PUBLIC_SITE_ORIGIN}.`
|
|
181
|
+
: status === 404
|
|
182
|
+
? " The resource may not exist or may have been deleted."
|
|
183
|
+
: status === 409
|
|
184
|
+
? " The job may not be in the expected state."
|
|
185
|
+
: status === 429
|
|
186
|
+
? " Rate limit exceeded — wait a moment and retry."
|
|
187
|
+
: status >= 500
|
|
188
|
+
? " Server error — retry later."
|
|
189
|
+
: "";
|
|
190
|
+
const rid = ` (request id: ${requestId} — include if contacting support)`;
|
|
191
|
+
return `${detail}${code}${hint}${rid}`;
|
|
192
|
+
}
|
|
193
|
+
function throwApiError(status, bodyText, requestId) {
|
|
194
|
+
const err = new Error(formatApiErrorMessage(status, bodyText, requestId));
|
|
195
|
+
err.httpStatus = status;
|
|
196
|
+
throw err;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* @param requestTimeoutMs Optional per-request timeout (default `BARIVIA_FETCH_TIMEOUT_MS`).
|
|
200
|
+
*/
|
|
201
|
+
export async function apiCall(method, path, body, extraHeaders, requestTimeoutMs) {
|
|
156
202
|
const url = `${API_URL}${path}`;
|
|
157
203
|
const contentType = extraHeaders?.["Content-Type"] ?? "application/json";
|
|
158
204
|
const requestId = Math.random().toString(36).slice(2, 10);
|
|
@@ -167,6 +213,7 @@ export async function apiCall(method, path, body, extraHeaders) {
|
|
|
167
213
|
serializedBody =
|
|
168
214
|
contentType === "application/json" ? JSON.stringify(body) : String(body);
|
|
169
215
|
}
|
|
216
|
+
const effectiveTimeout = requestTimeoutMs ?? FETCH_TIMEOUT_MS;
|
|
170
217
|
const t0 = Date.now();
|
|
171
218
|
console.error(`${new Date().toISOString()} API -> ${method} ${path} rid=${requestId}`);
|
|
172
219
|
let lastError;
|
|
@@ -176,7 +223,7 @@ export async function apiCall(method, path, body, extraHeaders) {
|
|
|
176
223
|
method,
|
|
177
224
|
headers,
|
|
178
225
|
body: serializedBody,
|
|
179
|
-
});
|
|
226
|
+
}, effectiveTimeout);
|
|
180
227
|
const text = await resp.text();
|
|
181
228
|
if (!resp.ok) {
|
|
182
229
|
if (attempt < MAX_RETRIES && isTransientError(null, resp.status)) {
|
|
@@ -184,23 +231,7 @@ export async function apiCall(method, path, body, extraHeaders) {
|
|
|
184
231
|
continue;
|
|
185
232
|
}
|
|
186
233
|
console.error(`${new Date().toISOString()} API <- ${resp.status} ${Date.now() - t0}ms rid=${requestId}`);
|
|
187
|
-
|
|
188
|
-
return JSON.parse(text);
|
|
189
|
-
}
|
|
190
|
-
catch {
|
|
191
|
-
return null;
|
|
192
|
-
} })();
|
|
193
|
-
const detail = errBody?.error ?? text;
|
|
194
|
-
const hint = resp.status === 400 ? " Check parameter types and required fields."
|
|
195
|
-
: resp.status === 401 ? " Check BARIVIA_API_KEY in your environment or regenerate at https://barivia.com/dashboard."
|
|
196
|
-
: resp.status === 404 ? " The resource may not exist or may have been deleted."
|
|
197
|
-
: resp.status === 409 ? " The job may not be in the expected state."
|
|
198
|
-
: resp.status === 429 ? " Rate limit exceeded — wait a moment and retry."
|
|
199
|
-
: "";
|
|
200
|
-
const code = errBody?.error_code ? ` (error_code: ${errBody.error_code})` : "";
|
|
201
|
-
const err = new Error(`${detail}${code}${hint}`);
|
|
202
|
-
err.httpStatus = resp.status;
|
|
203
|
-
throw err;
|
|
234
|
+
throwApiError(resp.status, text, requestId);
|
|
204
235
|
}
|
|
205
236
|
console.error(`${new Date().toISOString()} API <- ${resp.status} ${Date.now() - t0}ms rid=${requestId}`);
|
|
206
237
|
return JSON.parse(text);
|
|
@@ -211,27 +242,38 @@ export async function apiCall(method, path, body, extraHeaders) {
|
|
|
211
242
|
await new Promise((r) => setTimeout(r, 1000 * 2 ** attempt));
|
|
212
243
|
continue;
|
|
213
244
|
}
|
|
245
|
+
if (err instanceof DOMException &&
|
|
246
|
+
err.name === "AbortError" &&
|
|
247
|
+
!err.httpStatus) {
|
|
248
|
+
throw new Error(`Request timed out after ${effectiveTimeout}ms. Increase BARIVIA_FETCH_TIMEOUT_MS in your MCP env (e.g. 120000) for slow or large requests. (request id: ${requestId})`);
|
|
249
|
+
}
|
|
214
250
|
throw err;
|
|
215
251
|
}
|
|
216
252
|
}
|
|
217
253
|
throw lastError;
|
|
218
254
|
}
|
|
219
255
|
/** Fetch raw bytes from the API (for image downloads). */
|
|
220
|
-
export async function apiRawCall(path) {
|
|
256
|
+
export async function apiRawCall(path, requestTimeoutMs) {
|
|
221
257
|
const url = `${API_URL}${path}`;
|
|
258
|
+
const requestId = Math.random().toString(36).slice(2, 10);
|
|
259
|
+
const effectiveTimeout = requestTimeoutMs ?? FETCH_TIMEOUT_MS;
|
|
222
260
|
let lastError;
|
|
223
261
|
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
|
|
224
262
|
try {
|
|
225
263
|
const resp = await fetchWithTimeout(url, {
|
|
226
264
|
method: "GET",
|
|
227
|
-
headers: {
|
|
228
|
-
|
|
265
|
+
headers: {
|
|
266
|
+
Authorization: `Bearer ${API_KEY}`,
|
|
267
|
+
"X-Request-ID": requestId,
|
|
268
|
+
},
|
|
269
|
+
}, effectiveTimeout);
|
|
229
270
|
if (!resp.ok) {
|
|
230
271
|
if (attempt < MAX_RETRIES && isTransientError(null, resp.status)) {
|
|
231
272
|
await new Promise((r) => setTimeout(r, 1000 * 2 ** attempt));
|
|
232
273
|
continue;
|
|
233
274
|
}
|
|
234
|
-
|
|
275
|
+
const text = await resp.text();
|
|
276
|
+
throwApiError(resp.status, text, requestId);
|
|
235
277
|
}
|
|
236
278
|
const arrayBuf = await resp.arrayBuffer();
|
|
237
279
|
return {
|
|
@@ -245,6 +287,11 @@ export async function apiRawCall(path) {
|
|
|
245
287
|
await new Promise((r) => setTimeout(r, 1000 * 2 ** attempt));
|
|
246
288
|
continue;
|
|
247
289
|
}
|
|
290
|
+
if (err instanceof DOMException &&
|
|
291
|
+
err.name === "AbortError" &&
|
|
292
|
+
!err.httpStatus) {
|
|
293
|
+
throw new Error(`Request timed out after ${effectiveTimeout}ms. Increase BARIVIA_FETCH_TIMEOUT_MS (e.g. 120000) for large images. (request id: ${requestId})`);
|
|
294
|
+
}
|
|
248
295
|
throw err;
|
|
249
296
|
}
|
|
250
297
|
}
|
|
@@ -286,25 +333,34 @@ export async function pollUntilComplete(jobId, maxWaitMs = 30_000, intervalMs =
|
|
|
286
333
|
}
|
|
287
334
|
return { status: "timeout" };
|
|
288
335
|
}
|
|
289
|
-
|
|
336
|
+
function formatGuidanceScopeSuffix(config) {
|
|
337
|
+
const scope = config?.guidance_scope;
|
|
338
|
+
const ajt = scope?.allowed_job_types;
|
|
339
|
+
if (Array.isArray(ajt) && ajt.length > 0) {
|
|
340
|
+
return "\n\n(Your plan allows these training job types: " + ajt.map(String).join(", ") + ")";
|
|
341
|
+
}
|
|
342
|
+
return "";
|
|
343
|
+
}
|
|
344
|
+
/** Fetch training guidance from API (used by training_guidance tool). Domain knowledge returned when asked; valid license required. Hints are filtered by plan (allowed_job_types). */
|
|
290
345
|
export async function fetchTrainingGuidanceFromApi() {
|
|
291
346
|
try {
|
|
292
347
|
const config = (await apiCall("GET", "/v1/training/config"));
|
|
348
|
+
const scopeSuffix = formatGuidanceScopeSuffix(config);
|
|
293
349
|
const presetDesc = config?.preset_descriptions;
|
|
294
350
|
const presetBlock = Array.isArray(presetDesc) && presetDesc.length > 0
|
|
295
351
|
? "Presets: " + presetDesc.join(" | ") + "\n\n"
|
|
296
352
|
: "";
|
|
297
353
|
const hints = config?.training_hints;
|
|
298
354
|
if (Array.isArray(hints) && hints.length > 0) {
|
|
299
|
-
return presetBlock + "Parameter guidance (from API):\n- " + hints.join("\n- ");
|
|
355
|
+
return presetBlock + "Parameter guidance (from API):\n- " + hints.join("\n- ") + scopeSuffix;
|
|
300
356
|
}
|
|
301
357
|
const pg = config?.parameter_guidance;
|
|
302
358
|
if (pg && typeof pg === "object") {
|
|
303
359
|
const lines = Object.entries(pg).map(([k, v]) => `${k}: ${v}`);
|
|
304
|
-
return presetBlock + "Parameter guidance (from API):\n- " + lines.join("\n- ");
|
|
360
|
+
return presetBlock + "Parameter guidance (from API):\n- " + lines.join("\n- ") + scopeSuffix;
|
|
305
361
|
}
|
|
306
362
|
if (presetBlock)
|
|
307
|
-
return presetBlock + "No additional parameter guidance in config.";
|
|
363
|
+
return presetBlock + "No additional parameter guidance in config." + scopeSuffix;
|
|
308
364
|
}
|
|
309
365
|
catch (e) {
|
|
310
366
|
if (e?.httpStatus === 401 || e?.httpStatus === 403)
|
|
@@ -313,6 +369,25 @@ export async function fetchTrainingGuidanceFromApi() {
|
|
|
313
369
|
}
|
|
314
370
|
return "No parameter guidance available.";
|
|
315
371
|
}
|
|
372
|
+
/**
|
|
373
|
+
* Full MCP workflow + bootstrap text from API (tier-scoped). Null on network/parse failure (caller may show offline stub).
|
|
374
|
+
* Re-throws 401/403 so the MCP host surfaces auth errors.
|
|
375
|
+
*/
|
|
376
|
+
export async function fetchWorkflowGuideFromApi() {
|
|
377
|
+
try {
|
|
378
|
+
const data = (await apiCall("GET", "/v1/docs/workflow"));
|
|
379
|
+
const md = data?.workflow_markdown;
|
|
380
|
+
if (typeof md === "string" && md.trim().length > 0) {
|
|
381
|
+
return md.trim();
|
|
382
|
+
}
|
|
383
|
+
return null;
|
|
384
|
+
}
|
|
385
|
+
catch (e) {
|
|
386
|
+
if (e?.httpStatus === 401 || e?.httpStatus === 403)
|
|
387
|
+
throw e;
|
|
388
|
+
return null;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
316
391
|
// ---------------------------------------------------------------------------
|
|
317
392
|
// Image helpers
|
|
318
393
|
// ---------------------------------------------------------------------------
|
|
@@ -509,4 +584,3 @@ export async function loadViewHtml(viewName) {
|
|
|
509
584
|
}
|
|
510
585
|
return null;
|
|
511
586
|
}
|
|
512
|
-
//# sourceMappingURL=shared.js.map
|
package/dist/tools/account.js
CHANGED
package/dist/tools/datasets.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
import fs from "node:fs/promises";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
-
import { apiCall, getWorkspaceRootAsync, resolveFilePathForUpload, textResult, pollUntilComplete, } from "../shared.js";
|
|
4
|
+
import { apiCall, getWorkspaceRootAsync, resolveFilePathForUpload, textResult, pollUntilComplete, POLL_DERIVE_MAX_MS, UPLOAD_DATASET_TIMEOUT_MS, } from "../shared.js";
|
|
5
5
|
export function registerDatasetsTool(server) {
|
|
6
6
|
server.tool("datasets", `Manage datasets: upload, preview, list, subset, add_expression, or delete.
|
|
7
7
|
|
|
@@ -110,7 +110,7 @@ ESCALATION: If upload fails with column errors, open the file locally and verify
|
|
|
110
110
|
const data = (await apiCall("POST", "/v1/datasets", body, {
|
|
111
111
|
"X-Dataset-Name": name,
|
|
112
112
|
"Content-Type": "text/csv",
|
|
113
|
-
}));
|
|
113
|
+
}, UPLOAD_DATASET_TIMEOUT_MS));
|
|
114
114
|
const id = data.id ?? data.dataset_id;
|
|
115
115
|
if (id != null)
|
|
116
116
|
data.suggested_next_step = `Suggested next step: datasets(action=preview, dataset_id=${id}) to inspect columns before training.`;
|
|
@@ -284,7 +284,7 @@ ESCALATION: If upload fails with column errors, open the file locally and verify
|
|
|
284
284
|
body.options = options;
|
|
285
285
|
const data = (await apiCall("POST", `/v1/datasets/${dataset_id}/derive`, body));
|
|
286
286
|
const deriveJobId = data.id;
|
|
287
|
-
const poll = await pollUntilComplete(deriveJobId);
|
|
287
|
+
const poll = await pollUntilComplete(deriveJobId, POLL_DERIVE_MAX_MS);
|
|
288
288
|
if (poll.status === "completed") {
|
|
289
289
|
const results = (await apiCall("GET", `/v1/results/${deriveJobId}`));
|
|
290
290
|
const summary = (results.summary ?? {});
|
|
@@ -341,4 +341,3 @@ ESCALATION: If upload fails with column errors, open the file locally and verify
|
|
|
341
341
|
throw new Error("Invalid action");
|
|
342
342
|
});
|
|
343
343
|
}
|
|
344
|
-
//# sourceMappingURL=datasets.js.map
|
package/dist/tools/feedback.js
CHANGED
|
@@ -1,76 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
import { fetchWorkflowGuideFromApi } from "../shared.js";
|
|
2
|
+
/** Minimal orientation when the API is unreachable; full SOP lives on GET /v1/docs/workflow. */
|
|
3
|
+
const OFFLINE_STUB = `## Offline / API unavailable
|
|
2
4
|
|
|
3
|
-
|
|
5
|
+
Configure \`BARIVIA_API_KEY\` and optional \`BARIVIA_API_URL\`, then call **guide_barsom_workflow** again. Full tool map, async rules, training modes, and step-by-step SOP are loaded from the Barivia API (authenticated) and scoped to your plan.
|
|
4
6
|
|
|
5
|
-
**
|
|
6
|
-
- \`datasets\` — upload, preview, list, subset, delete, add_expression
|
|
7
|
-
- \`jobs\` — \`train_map\`, \`train_siom_map\`, \`train_floop_siom\` (and deprecated alias \`train_floop_chain\`), plus \`status\`, \`list\`, \`compare\`, \`cancel\`, \`delete\`, \`batch_predict\`, \`run_baseline_study\`
|
|
8
|
-
- \`results\` — get, recolor, download, export, transition_flow
|
|
9
|
-
- \`inference\` — predict, enrich, compare, report, project_columns
|
|
10
|
-
- \`account\` — status, compute credits, history
|
|
11
|
-
- \`training_guidance\` — API-served parameter hints (grid, epochs, presets, SIOM/FLooP knobs)
|
|
12
|
-
- \`training_prep\`, \`results_explorer\`, \`training_monitor\` — **optional** rich UIs (see below)
|
|
13
|
-
- \`send_feedback\`, \`guide_barsom_workflow\` (this tool)
|
|
7
|
+
**Core tools:** \`datasets\`, \`jobs\` (train_map, train_siom_map, train_floop_siom where entitled), \`results\`, \`inference\`, \`account\`, \`training_guidance\`, \`guide_barsom_workflow\`.
|
|
14
8
|
|
|
15
|
-
**
|
|
16
|
-
|
|
17
|
-
**Training modes (when to use which):**
|
|
18
|
-
- **Standard SOM** — \`jobs(action=train_map)\`: fixed hex/grid map.
|
|
19
|
-
- **SIOM** — \`jobs(action=train_siom_map)\`: same grid flow with coverage regularization.
|
|
20
|
-
- **FLooP-SIOM** — \`jobs(action=train_floop_siom)\`: growing manifold; default \`topology=free\` (CHL); optional \`topology=chain\`.
|
|
21
|
-
|
|
22
|
-
**MCP Apps (optional rich UI):** **Not required** for any outcome—the same work completes with \`jobs\`, \`results\`, and thread text alone. **Recommended** for clarity: **preparation** → \`training_prep\`; **postprocessing / exploration** → \`results_explorer\` after completion. **Monitoring** → \`training_monitor(job_id)\` is optional polish (charts); \`jobs(action=status)\` is sufficient. If the host has no MCP Apps, ignore these or use standalone URLs from tool responses when offered.
|
|
23
|
-
|
|
24
|
-
**Where to go next:** Parameter presets and field-level hints → \`training_guidance\` or the \`prepare_training\` prompt. Full step order → **Workflow (SOP)** below.
|
|
25
|
-
|
|
26
|
-
---
|
|
27
|
-
|
|
28
|
-
## Workflow (SOP)
|
|
29
|
-
|
|
30
|
-
`;
|
|
31
|
-
const SOP = `Step 1: Upload Data
|
|
32
|
-
- Use \`datasets(action=upload)\` with \`file_path\` to your CSV (server reads from workspace root; token-efficient). Use \`csv_data\` only for small inline pastes.
|
|
33
|
-
- BEFORE UPLOADING: Clean the dataset to remove NaNs or malformed data.
|
|
34
|
-
- Capture the \`dataset_id\` returned.
|
|
35
|
-
|
|
36
|
-
Step 2: Preview & Preprocess
|
|
37
|
-
- Use \`datasets(action=preview)\` to inspect columns, ranges, and types.
|
|
38
|
-
- Check for skewed columns requiring 'log' or 'sqrt' transforms.
|
|
39
|
-
- Check for cyclical or temporal features (hours, days) requiring \`cyclic_features\` or \`temporal_features\` during training.
|
|
40
|
-
- Raw categorical/text columns usually stay out of the first map. If one really matters, use explicit baseline \`categorical_features\` encoding rather than assuming advanced categorical embeddings.
|
|
41
|
-
- *(Optional UI)* \`training_prep(dataset_id=...)\` helps review variables, transforms, and hyperparameters before submit—not required if you train directly with \`jobs\`.
|
|
42
|
-
|
|
43
|
-
Step 3: Train the map
|
|
44
|
-
- Choose one: \`jobs(action=train_map, dataset_id=...)\`, \`jobs(action=train_siom_map, dataset_id=...)\`, or \`jobs(action=train_floop_siom, dataset_id=...)\`.
|
|
45
|
-
- Carefully select columns to include (start with 5–10).
|
|
46
|
-
- Assign \`feature_weights\` when some numeric or encoded features should matter more than others.
|
|
47
|
-
- Wait for the returned \`job_id\`.
|
|
48
|
-
- For projection and inference, use the same job_id from train_som (or the new job_id returned by recolor/project when applicable).
|
|
49
|
-
- *(Optional UI)* After submit, \`training_monitor(job_id=...)\` can show progress visually; **\`jobs(action=status)\` alone is enough** to know when training finished.
|
|
50
|
-
|
|
51
|
-
Step 4: Wait for Completion (ASYNC POLLING)
|
|
52
|
-
- Use \`jobs(action=status, job_id=...)\` every 10–15 seconds.
|
|
53
|
-
- Wait until status is "completed". DO NOT assume failure before 3 minutes (or longer for large grids).
|
|
54
|
-
- If it fails, read the error message and adjust parameters (e.g., reduce grid size, fix column names).
|
|
55
|
-
|
|
56
|
-
Step 5: Analyze and Export
|
|
57
|
-
- Once completed, use \`results(action=get, job_id=...)\` to get the map, metrics (QE, TE, Silhouette, etc.), and figures (U-matrix, component planes, clusters, hit histogram). There is no separate \`analyze\` tool — all visualizations and metrics come from \`results(action=get)\`.
|
|
58
|
-
- *(Optional UI)* \`results_explorer(job_id=...)\` is especially useful to browse figures and metrics interactively; **\`results(action=get)\` is sufficient** without it.
|
|
59
|
-
Step 5b (optional): Use \`jobs(action=compare, job_ids=[id1, id2, ...])\` to compare multiple train_map runs (QE, TE, explained variance, silhouette) before committing to one.
|
|
60
|
-
|
|
61
|
-
What you can do at each step:
|
|
62
|
-
- After upload: datasets(preview), datasets(subset), datasets(add_expression), datasets(delete).
|
|
63
|
-
- After training completes: results(get/download/export), results(recolor), results(transition_flow), jobs(compare), inference(predict/enrich/compare/project_columns/report).`;
|
|
9
|
+
**Parameter hints:** call \`training_guidance\` (also API-scoped). **Async:** poll \`jobs(action=status)\` every 10–15s after submit.`;
|
|
64
10
|
export function registerGuideBarsomTool(server) {
|
|
65
|
-
server.tool("guide_barsom_workflow",
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
],
|
|
73
|
-
};
|
|
11
|
+
server.tool("guide_barsom_workflow", "Ground-truth orientation for this MCP: proxy model, tool categories, async rules, training modes, and step-by-step SOP — loaded from the Barivia API when online (tier-scoped to allowed_job_types). Call at the start of mapping work. Offline: returns a short stub. For field-level training parameters, use training_guidance or prepare_training.", {}, async () => {
|
|
12
|
+
const md = await fetchWorkflowGuideFromApi();
|
|
13
|
+
if (md) {
|
|
14
|
+
const text = "Source: Barivia API (`GET /v1/docs/workflow`). Text below is scoped to your API key / plan.\n\n" + md;
|
|
15
|
+
return { content: [{ type: "text", text }] };
|
|
16
|
+
}
|
|
17
|
+
return { content: [{ type: "text", text: OFFLINE_STUB }] };
|
|
74
18
|
});
|
|
75
19
|
}
|
|
76
|
-
//# sourceMappingURL=guide_barsom.js.map
|
package/dist/tools/inference.js
CHANGED
package/dist/tools/jobs.js
CHANGED
|
@@ -9,7 +9,7 @@ export const JOBS_DESCRIPTION_BASE = `Manage and inspect jobs.
|
|
|
9
9
|
| compare | Picking the best training run from a set of completed jobs |
|
|
10
10
|
| train_map | Submitting a new map training job — returns job_id for polling |
|
|
11
11
|
| train_siom_map | Submitting a self-interacting map training job — same map flow with SIOM coverage control |
|
|
12
|
-
| train_floop_siom | Submitting a FLooP-SIOM job (growing manifold; default topology=free / CHL) |
|
|
12
|
+
| train_floop_siom | Submitting a FLooP-SIOM job (growing manifold; default topology=free / CHL) — requires Premium or Enterprise plan (all_algorithms) |
|
|
13
13
|
| train_floop_chain | Deprecated alias for train_floop_siom — same behavior; prefer train_floop_siom |
|
|
14
14
|
| cancel | Stopping a running or pending job to free the worker |
|
|
15
15
|
| delete | Permanently removing a job and all its S3 result files |
|
|
@@ -36,7 +36,7 @@ action=train_map / train_siom_map: Submits a grid-map training job. Returns job_
|
|
|
36
36
|
normalize: "auto" (default) = scale only non-cyclic features; "all" = scale every feature. Use "auto" when using cyclic_features.
|
|
37
37
|
categorical_features: optional baseline categorical support using explicit weighted one-hot encoding. Provide the raw column name, allowed categories, and a weight. Advanced categorical embeddings are intentionally outside this default tool surface.
|
|
38
38
|
train_siom_map only: siom_feature_geometry l2 (default) | mixed | auto — torus distance on cyclic (cos,sin) pairs when mixed or auto with cyclic encodings. siom_qe_backend cpu|cuda|auto and siom_qe_batch_size align siom_qe with training geometry when mixed.
|
|
39
|
-
action=train_floop_siom (preferred) or train_floop_chain (deprecated alias): Submits FLooP-SIOM — a growing node-budget manifold instead of a fixed hex grid. Default topology is free (CHL dynamic graph); topology=chain is optional for a strict 1D linked-list backbone.
|
|
39
|
+
action=train_floop_siom (preferred) or train_floop_chain (deprecated alias): Submits FLooP-SIOM — a growing node-budget manifold instead of a fixed hex grid. **Only if the API key’s plan includes all_algorithms** (Premium or Enterprise); otherwise the API returns a clear upgrade message. Default topology is free (CHL dynamic graph); topology=chain is optional for a strict 1D linked-list backbone.
|
|
40
40
|
Key params: topology (default free), max_nodes, effort, gamma, siom_decay.
|
|
41
41
|
max_nodes is a total node budget, not a grid width or area. If omitted, the backend uses a dataset-size heuristic (roughly 2*sqrt(n_samples), capped for stability).
|
|
42
42
|
effort controls passes only: quick≈15, standard≈30, thorough≈60. If coverage collapses, reduce max_nodes before increasing effort.
|
|
@@ -512,4 +512,3 @@ export function registerJobsTool(server, description) {
|
|
|
512
512
|
throw new Error("Invalid action");
|
|
513
513
|
});
|
|
514
514
|
}
|
|
515
|
-
//# sourceMappingURL=jobs.js.map
|
package/dist/tools/results.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { fetchTrainingGuidanceFromApi } from "../shared.js";
|
|
2
2
|
export function registerTrainingGuidanceTool(server) {
|
|
3
|
-
server.tool("training_guidance", "Returns parameter guidance for training jobs (grid, epochs, batch, model, periodic, SIOM/FLooP fields, categorical baselines). Domain knowledge is served from
|
|
3
|
+
server.tool("training_guidance", "Returns parameter guidance for training jobs (grid, epochs, batch, model, periodic, SIOM/FLooP fields where your plan allows, categorical baselines). Domain knowledge is served from GET /v1/training/config and filtered to your allowed_job_types; requires valid API key. For full proxy orientation and SOP, call guide_barsom_workflow (loads GET /v1/docs/workflow). Optional visual workflows: training_prep (prep), results_explorer (postprocess)—not required; jobs + results are sufficient.", {}, async () => {
|
|
4
4
|
const text = await fetchTrainingGuidanceFromApi();
|
|
5
5
|
return { content: [{ type: "text", text }] };
|
|
6
6
|
});
|
|
7
7
|
}
|
|
8
|
-
//# sourceMappingURL=training_guidance.js.map
|
|
@@ -353,4 +353,3 @@ export function registerTrainingPrepTools(server) {
|
|
|
353
353
|
}, `Training job submitted from reviewed prep. Job ID: ${jobId}\nPoll with jobs(action=status, job_id="${jobId}") until complete, then use results(action=get, job_id="${jobId}").`);
|
|
354
354
|
});
|
|
355
355
|
}
|
|
356
|
-
//# sourceMappingURL=training_prep.js.map
|
package/dist/viz-server.js
CHANGED