@barivia/barmesh-mcp 0.8.8 → 0.8.9
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/dist/index.js +1 -1
- package/dist/shared.js +1 -1
- package/dist/tools/cfd.js +34 -36
- package/dist/tools/guide.js +5 -20
- package/package.json +1 -1
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
|
|
2
|
+
import{McpServer as e}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as r}from"@modelcontextprotocol/sdk/server/stdio.js";import{getUiCapability as o,registerAppResource as s,RESOURCE_MIME_TYPE as t}from"@modelcontextprotocol/ext-apps/server";import{startVizServer as n}from"./viz-server.js";import{API_KEY as i,CLIENT_VERSION as a,apiCall as m,apiRawCall as l,loadViewHtml as c,setVizPort as p,setClientSupportsMcpApps as h}from"./shared.js";import{registerGuideTool as d}from"./tools/guide.js";import{registerDatasetsTool as _}from"./tools/datasets.js";import{registerCfdTools as b}from"./tools/cfd.js";import{registerJobsTool as u}from"./tools/jobs.js";import{registerResultsTool as f}from"./tools/results.js";import{registerResultsExplorerTool as v,RESULTS_EXPLORER_URI as y}from"./tools/barmesh_results_explorer.js";import{registerTrainingMonitorTool as I,TRAINING_MONITOR_URI as w}from"./tools/training_monitor.js";import{registerFeedbackTool as g}from"./tools/feedback.js";i||(console.error("Error: BARIVIA_API_KEY not set. Set it in your MCP client config."),process.exit(1));(async function(){const i=new e({name:"barmesh",version:a},{instructions:"# Barivia barmesh — CFD mesh-convergence analytics\n\n## Bootstrap (do this first)\n\nCall `barmesh_guide_workflow` (plan-scoped) and `barmesh_prepare_mesh_data` before upload/submit. Method details and mesh-prep recipe come from the API when your key has the CFD entitlement.\n\n## Tracks (names only)\n\n- `barmesh_mesh_convergence` — field-level mesh comparison (SOM fingerprints)\n- `barmesh_richardson` — classical Richardson/GCI on scalar QoIs\n\n## Workflow (short)\n\n1. `barmesh_guide_workflow`\n2. `barmesh_prepare_mesh_data`\n3. `barmesh_datasets(upload)` → preview\n4. Submit mesh_convergence and/or richardson → job_id\n5. `barmesh_training_monitor` or `barmesh_jobs(monitor/status)`\n6. `barmesh_results(get)` → `barmesh_results_explorer`\n\nInventory: `barmesh_jobs(inventory)` or list datasets+jobs. Set description/tags on upload/submit.\n\n## UI / outages\n\nTool results lead with a localhost viz URL and `ui_delivery` — follow `hint_for_agent`. Env: `BARIVIA_UI_DELIVERY`, `BARIVIA_VIZ_PORT`.\nOn `api_unreachable`: one calm line; honor `retry_after_sec`; use `barmesh_api_health`; keep reviewing last good figures. `barmesh_send_feedback` queues deferred drafts when the API is down."});s(i,y,y,{mimeType:t},async()=>{const e=await c("barmesh-results-explorer");return{contents:[{uri:y,mimeType:t,text:e??"<html><body>Results Explorer view not built yet. Run: npm run build:views</body></html>"}]}}),s(i,w,w,{mimeType:t},async()=>{const e=await c("barmesh-training-monitor");return{contents:[{uri:w,mimeType:t,text:e??"<html><body>Training Monitor view not built yet. Run: npm run build:views</body></html>"}]}}),d(i),v(i),_(i),b(i),u(i),I(i),f(i),g(i);try{const e=await n(m,l,c);p(e)}catch(e){process.env.BARIVIA_VIZ_PORT&&console.error("barmesh viz server failed to start:",e)}const j=i.server;j.oninitialized=()=>{const e=j.getClientCapabilities(),r=o(e);h(!!r?.mimeTypes?.includes(t))};const A=new r;await i.connect(A),console.error(`barmesh-mcp ${a} ready (API: ${process.env.BARIVIA_API_URL??"https://api.barivia.se"})`)})().catch(e=>{console.error("Fatal error starting barmesh-mcp:",e),process.exit(1)});
|
package/dist/shared.js
CHANGED
|
@@ -35,7 +35,7 @@ function newRequestId() {
|
|
|
35
35
|
return randomUUID();
|
|
36
36
|
}
|
|
37
37
|
/** Single source of truth for the proxy version. Keep in sync with package.json on bump. */
|
|
38
|
-
export const CLIENT_VERSION = "0.8.
|
|
38
|
+
export const CLIENT_VERSION = "0.8.9";
|
|
39
39
|
export const PUBLIC_SITE_ORIGIN = "https://barivia.se";
|
|
40
40
|
/** Large per-cell CSV uploads may exceed the default fetch timeout. */
|
|
41
41
|
export const UPLOAD_DATASET_TIMEOUT_MS = 180_000;
|
package/dist/tools/cfd.js
CHANGED
|
@@ -5,34 +5,33 @@ import { pollCfdPrepareIfPresent } from "../cfd_prepare.js";
|
|
|
5
5
|
export function registerCfdTools(server) {
|
|
6
6
|
registerAuditedTool(server, "barmesh_mesh_convergence", `Run SOM-based mesh-convergence analysis on an uploaded combined per-cell CSV.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
COMMON MISTAKES: omitting feature_columns (required); choosing a reference_mesh label that is not present; forgetting the cell-volume column at upload time; multi-topology studies (uniform U + graded G meshes) without explicit mesh_order — equal cell counts sort U-then-G and invent bogus stepwise pairs (U160|G20). Pass mesh_order coarse→fine interleaved by refinement (U20,G20,U40,G40,…) or use preset=cavity which defaults interleaved when U/G labels are detected.`, {
|
|
8
|
+
BEST FOR: Field-level mesh-refinement comparison (not a single scalar QoI).
|
|
9
|
+
NOT FOR: Classical GCI on scalars — use barmesh_richardson.
|
|
10
|
+
ASYNC: Returns job_id; poll barmesh_jobs(status) every 10–20s; then barmesh_results(get).
|
|
11
|
+
Call **barmesh_guide_workflow** / **barmesh_prepare_mesh_data** for method details, mesh_order rules, and prep recipe (API, CFD entitlement).
|
|
12
|
+
COMMON MISTAKES: omitting feature_columns; bad reference_mesh label; missing volume column — see prepare_mesh_data.`, {
|
|
14
13
|
dataset_id: z.string().describe("Dataset ID from barmesh_datasets(upload)"),
|
|
15
|
-
feature_columns: z.array(z.string()).describe("Per-cell numeric feature columns
|
|
16
|
-
preset: z.enum(["generic", "cavity", "pitz", "datacenter"]).optional().describe("Hyperparameter preset
|
|
17
|
-
mesh_column: z.string().optional().describe("
|
|
18
|
-
volume_column: z.string().optional().describe("Cell-volume column
|
|
19
|
-
reference_mesh: z.string().optional().describe("
|
|
20
|
-
mesh_order: z.array(z.string()).optional().describe("Explicit coarse
|
|
21
|
-
grid: z.array(z.number().int()).optional().describe("SOM grid [rows, cols]
|
|
22
|
-
epochs: z.array(z.number().int()).optional().describe("[ordering, convergence] epochs
|
|
23
|
-
batch_size: z.number().int().optional().describe("SOM batch size
|
|
24
|
-
sigma_f: z.number().optional().describe("Final ordering neighborhood width
|
|
25
|
-
backend: z.enum(["auto", "cpu", "gpu", "gpu_graphs"]).optional().describe("Compute backend
|
|
26
|
-
stratify_scale: z.number().optional().describe("[0,1] per-mesh training-row cap
|
|
27
|
-
emd_method: z.enum(["exact", "sinkhorn"]).optional().describe("EMD solver
|
|
28
|
-
te_panel_size: z.number().int().optional().describe("
|
|
14
|
+
feature_columns: z.array(z.string()).describe("Per-cell numeric feature columns for the SOM"),
|
|
15
|
+
preset: z.enum(["generic", "cavity", "pitz", "datacenter"]).optional().describe("Hyperparameter preset (default generic) — see barmesh_guide_workflow"),
|
|
16
|
+
mesh_column: z.string().optional().describe("Mesh label column (default mesh_id)"),
|
|
17
|
+
volume_column: z.string().optional().describe("Cell-volume column (default V)"),
|
|
18
|
+
reference_mesh: z.string().optional().describe("Reference mesh label (default: finest / most cells)"),
|
|
19
|
+
mesh_order: z.array(z.string()).optional().describe("Explicit coarse→fine mesh order — see barmesh_prepare_mesh_data"),
|
|
20
|
+
grid: z.array(z.number().int()).optional().describe("SOM grid [rows, cols] override"),
|
|
21
|
+
epochs: z.array(z.number().int()).optional().describe("[ordering, convergence] epochs override"),
|
|
22
|
+
batch_size: z.number().int().optional().describe("SOM batch size override"),
|
|
23
|
+
sigma_f: z.number().optional().describe("Final ordering neighborhood width override"),
|
|
24
|
+
backend: z.enum(["auto", "cpu", "gpu", "gpu_graphs"]).optional().describe("Compute backend"),
|
|
25
|
+
stratify_scale: z.number().optional().describe("[0,1] per-mesh training-row cap"),
|
|
26
|
+
emd_method: z.enum(["exact", "sinkhorn"]).optional().describe("EMD solver — see barmesh_guide_workflow"),
|
|
27
|
+
te_panel_size: z.number().int().optional().describe("Live TE evaluation panel size"),
|
|
29
28
|
te_inner_samples: z.number().int().optional().describe("Deprecated alias for te_panel_size"),
|
|
30
|
-
component_planes_physical: z.boolean().optional().describe("Physical-scale component-plane colorbars
|
|
29
|
+
component_planes_physical: z.boolean().optional().describe("Physical-scale component-plane colorbars"),
|
|
31
30
|
figures: z.boolean().optional().describe("Generate publication figures (default true)"),
|
|
32
|
-
transforms: z.record(z.enum(["log", "log1p", "log10", "sqrt", "square", "abs", "invert", "none"])).optional().describe("Per-feature transform
|
|
33
|
-
normalize: z.union([z.enum(["all", "auto", "mad", "sigmoidal", "sepd"]), z.array(z.string())]).optional().describe("
|
|
34
|
-
normalization_methods: z.record(z.enum(["zscore", "mad", "sigmoidal", "sepd", "none"])).optional().describe("Per-feature normalization override
|
|
35
|
-
row_range: z.tuple([z.number().int().min(1), z.number().int().min(1)]).optional().describe("1-based inclusive [start, end] row slice
|
|
31
|
+
transforms: z.record(z.enum(["log", "log1p", "log10", "sqrt", "square", "abs", "invert", "none"])).optional().describe("Per-feature transform before normalization"),
|
|
32
|
+
normalize: z.union([z.enum(["all", "auto", "mad", "sigmoidal", "sepd"]), z.array(z.string())]).optional().describe("SOM feature normalization mode"),
|
|
33
|
+
normalization_methods: z.record(z.enum(["zscore", "mad", "sigmoidal", "sepd", "none"])).optional().describe("Per-feature normalization override"),
|
|
34
|
+
row_range: z.tuple([z.number().int().min(1), z.number().int().min(1)]).optional().describe("1-based inclusive [start, end] row slice"),
|
|
36
35
|
label: z.string().optional().describe("Optional job label"),
|
|
37
36
|
description: z.string().optional().describe("Optional free-text description for inventory"),
|
|
38
37
|
tags: z.array(z.string()).optional().describe("Optional tags for inventory/navigation"),
|
|
@@ -63,21 +62,20 @@ COMMON MISTAKES: omitting feature_columns (required); choosing a reference_mesh
|
|
|
63
62
|
}
|
|
64
63
|
return textResult(data);
|
|
65
64
|
});
|
|
66
|
-
registerAuditedTool(server, "barmesh_richardson", `Run classical Richardson extrapolation / Grid Convergence Index (GCI) on scalar
|
|
67
|
-
|
|
68
|
-
What it does: from a small CSV with one row per mesh (a mesh label, a representative cell size h or a cell count, and one or more QoI columns), slides the three-level Celik (2008) GCI over consecutive mesh triplets (finest first) and reports the observed order p, the extrapolated value, and the fine-grid GCI per triplet per QoI.
|
|
65
|
+
registerAuditedTool(server, "barmesh_richardson", `Run classical Richardson extrapolation / Grid Convergence Index (GCI) on scalar QoIs.
|
|
69
66
|
|
|
70
|
-
BEST FOR: Scalar benchmarks
|
|
71
|
-
NOT FOR: High-dimensional field comparison — use barmesh_mesh_convergence
|
|
72
|
-
ASYNC: queued job; poll barmesh_jobs(
|
|
73
|
-
|
|
67
|
+
BEST FOR: Scalar benchmarks where classical asymptotic-convergence checks are expected.
|
|
68
|
+
NOT FOR: High-dimensional field comparison — use barmesh_mesh_convergence.
|
|
69
|
+
ASYNC: queued job; poll barmesh_jobs(status), then barmesh_results(get).
|
|
70
|
+
Method details (Fs, one-family-per-CSV, triplets): **barmesh_guide_workflow**.
|
|
71
|
+
COMMON MISTAKES: missing h_column or n_cells_column; mixing mesh families — see guide.`, {
|
|
74
72
|
dataset_id: z.string().describe("Dataset ID (one row per mesh)"),
|
|
75
73
|
qoi_columns: z.array(z.string()).describe("Scalar QoI column names to extrapolate"),
|
|
76
74
|
mesh_column: z.string().optional().describe("Mesh label column (default mesh_id)"),
|
|
77
|
-
h_column: z.string().optional().describe("Representative cell-size column (
|
|
78
|
-
n_cells_column: z.string().optional().describe("Cell-count column
|
|
79
|
-
dimension: z.number().int().optional().describe("Spatial dimension
|
|
80
|
-
safety_factor: z.number().optional().describe("GCI safety factor
|
|
75
|
+
h_column: z.string().optional().describe("Representative cell-size column (or use n_cells_column)"),
|
|
76
|
+
n_cells_column: z.string().optional().describe("Cell-count column (alternative to h_column)"),
|
|
77
|
+
dimension: z.number().int().optional().describe("Spatial dimension for h from cell count"),
|
|
78
|
+
safety_factor: z.number().optional().describe("GCI safety factor — see barmesh_guide_workflow"),
|
|
81
79
|
label: z.string().optional().describe("Optional job label"),
|
|
82
80
|
description: z.string().optional().describe("Optional free-text description for inventory"),
|
|
83
81
|
tags: z.array(z.string()).optional().describe("Optional tags for inventory/navigation"),
|
package/dist/tools/guide.js
CHANGED
|
@@ -3,27 +3,12 @@ import { apiCall, probeApiHealth, structuredTextResult, textResult } from "../sh
|
|
|
3
3
|
import { listDeferredFeedback } from "../deferred_feedback.js";
|
|
4
4
|
const OFFLINE_GUIDE = `Mesh analysis API temporarily unavailable — figures already on disk stay available; new jobs/feedback will wait.
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
Say the API is unavailable plainly; the proxy already burst-retried (~3×2s) — wait ~30s before another round. Keep reviewing the last good distances/figures; do not treat the session as failed.
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
- barmesh_richardson — classical Richardson / GCI on scalar QoIs (one mesh family per CSV: uniform OR graded, not mixed)
|
|
8
|
+
When reconnecting (BARIVIA_API_KEY / BARIVIA_API_URL), call barmesh_guide_workflow again for the plan-scoped workflow.`;
|
|
9
|
+
const OFFLINE_PREP = `API unreachable — cannot load the CFD mesh-prep recipe.
|
|
11
10
|
|
|
12
|
-
|
|
13
|
-
1. barmesh_prepare_mesh_data — recipe for the combined per-cell CSV (mesh_id + features + cell volume V)
|
|
14
|
-
2. barmesh_datasets(upload) → barmesh_datasets(preview)
|
|
15
|
-
3. barmesh_mesh_convergence and/or barmesh_richardson — returns job_id
|
|
16
|
-
- Multi-topology cavity studies: pass mesh_order interleaved (U20,G20,U40,G40,…) or preset=cavity
|
|
17
|
-
4. barmesh_training_monitor (visual MCP App) or barmesh_jobs(action=monitor) headless — poll until complete
|
|
18
|
-
5. barmesh_results(action=get) → barmesh_results_explorer for figures (mesh_convergence) or richardson_gci.csv summary (Richardson)
|
|
19
|
-
|
|
20
|
-
(Set BARIVIA_API_KEY / BARIVIA_API_URL when reconnecting.)`;
|
|
21
|
-
const OFFLINE_PREP = `barmesh mesh-data prep (offline summary; API unreachable):
|
|
22
|
-
Build ONE combined per-cell CSV across all meshes of the refinement study:
|
|
23
|
-
- one row per cell; a mesh label column (mesh_id); the physical channels you want compared (e.g. p, U_mag, k, log_epsilon — log-compress turbulence quantities); and a cell-volume column (V) for fingerprint weighting.
|
|
24
|
-
- keep the SAME feature columns across every mesh; pick the finest mesh as the reference.
|
|
25
|
-
- multi-topology (U + G): pass mesh_order coarse→fine interleaved by refinement (U20,G20,U40,G40,U80,G80,U160,G160) or use preset=cavity.
|
|
26
|
-
Then: barmesh_datasets(upload) -> barmesh_mesh_convergence. (Set BARIVIA_API_KEY / BARIVIA_API_URL.)`;
|
|
11
|
+
Retry when BARIVIA_API_KEY / BARIVIA_API_URL reconnect, then call barmesh_prepare_mesh_data again (entitlement-scoped).`;
|
|
27
12
|
export function registerGuideTool(server) {
|
|
28
13
|
registerAuditedTool(server, "barmesh_guide_workflow", `Get the barmesh CFD mesh-convergence workflow and tool map from the API (tier-scoped).
|
|
29
14
|
|
|
@@ -49,7 +34,7 @@ UNAVAILABLE: If the API is down, this tool returns a calm offline summary — sa
|
|
|
49
34
|
|
|
50
35
|
BEST FOR: Before barmesh_datasets(upload) — tells you which physical channels to extract, how to label meshes (mesh_id), the cell-volume column (V), and how to pick the reference mesh.
|
|
51
36
|
NOT FOR: Submitting jobs — after preparing the CSV, use barmesh_datasets(upload) then barmesh_mesh_convergence.
|
|
52
|
-
COMMON MISTAKES:
|
|
37
|
+
COMMON MISTAKES: missing volume column; mismatched channels across meshes; multi-topology order issues — full recipe is in the API response when entitled.`, {}, async () => {
|
|
53
38
|
try {
|
|
54
39
|
const data = (await apiCall("GET", "/v1/cfd/prep"));
|
|
55
40
|
return textResult({ recipe: data.recipe, entitled: data.entitled });
|