formlab-mcp 0.6.12 → 0.6.14
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 +1 -1
- package/package.json +1 -1
- package/server.json +2 -2
- package/tools/lab.js +20 -0
package/README.md
CHANGED
|
@@ -37,7 +37,7 @@ Ask Claude (or another MCP client) things like:
|
|
|
37
37
|
| `list_lots` | Inventory lots across ingredients (each a received batch with its own remaining balance, supplier, expiry). Filters: `ingredient_id`, `expiring_within_days`, `status` |
|
|
38
38
|
| `list_inventory` | Portfolio stock rollup — one row per ingredient with on-hand qty, summed lot balance, nearest expiry, and a low-stock flag (on-hand ≤ `reorderThreshold`, or zero). Filters: `low_stock_only`, `expiring_within_days`, `family` |
|
|
39
39
|
| `list_batches` | Filtered list of production / lab-prep events |
|
|
40
|
-
| `get_batch` | Full record + actual composition, measured/derived **actual volume** (mass ÷ density, never a sum of per-ingredient volumes), the **process** method + any **process-factor values** (DOE inputs), samples + blend lineage |
|
|
40
|
+
| `get_batch` | Full record + actual composition, measured/derived **actual volume** (mass ÷ density, never a sum of per-ingredient volumes) and **actual mass** (yield, else summed inputs, else measured volume × density), the **process** method + any **process-factor values** (DOE inputs), samples + blend lineage |
|
|
41
41
|
| `list_samples` | Filtered list of physical specimens |
|
|
42
42
|
| `get_sample` | Full record + canonical variant + test reports + blend lineage |
|
|
43
43
|
| `list_test_results` | Filtered list of test reports (by sample, parameter, **measured-value range** (`value_min`/`value_max`), date, or lab) |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "formlab-mcp",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.14",
|
|
4
4
|
"mcpName": "io.github.juliu1980/formlab-mcp",
|
|
5
5
|
"description": "Read-only Model Context Protocol server for FormLab — lets Claude (and other MCP clients) read and analyze your FormLab data, from a local export file OR your live cloud workspace.",
|
|
6
6
|
"type": "module",
|
package/server.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
3
|
"name": "io.github.juliu1980/formlab-mcp",
|
|
4
4
|
"description": "Read-only MCP for FormLab — let Claude query your formulation lab. Free reads a local export; Pro connects to your live cloud workspace with a dedicated read-only token.",
|
|
5
|
-
"version": "0.6.
|
|
5
|
+
"version": "0.6.14",
|
|
6
6
|
"websiteUrl": "https://formvix.com/mcp",
|
|
7
7
|
"repository": {
|
|
8
8
|
"url": "https://github.com/juliu1980/FormLab",
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
{
|
|
14
14
|
"registryType": "npm",
|
|
15
15
|
"identifier": "formlab-mcp",
|
|
16
|
-
"version": "0.6.
|
|
16
|
+
"version": "0.6.14",
|
|
17
17
|
"runtimeHint": "npx",
|
|
18
18
|
"transport": {
|
|
19
19
|
"type": "stdio"
|
package/tools/lab.js
CHANGED
|
@@ -26,6 +26,17 @@ function _batchActualMassKg(b) {
|
|
|
26
26
|
for (const c of b.actualComposition) { const kg = _massToKg(parseFloat(c.amount), c.unit); if (kg != null) { t += kg; any = true; } }
|
|
27
27
|
if (any) return t;
|
|
28
28
|
}
|
|
29
|
+
// Volume-anchored batch (no weighed mass above): mass = measured volume ×
|
|
30
|
+
// measured density (V·ρ — always valid; summing per-ingredient volumes is
|
|
31
|
+
// not). Mirrors FormLab's js/views/batches.js _batchActualMassKg. The app
|
|
32
|
+
// also falls back to the formula's estimated density; MCP stays exact and
|
|
33
|
+
// reports null rather than an estimate. Recursion-safe: _batchActualVolume
|
|
34
|
+
// calls back into mass only when measuredVolume is ABSENT.
|
|
35
|
+
const mv = parseFloat(b.measuredVolume), d = parseFloat(b.measuredDensity);
|
|
36
|
+
if (isFinite(mv) && mv > 0 && isFinite(d) && d > 0) {
|
|
37
|
+
const L = _volToL(mv, b.measuredVolumeUnit || 'L');
|
|
38
|
+
if (L != null) return L * d; // kg (d in g/mL === kg/L)
|
|
39
|
+
}
|
|
29
40
|
return null;
|
|
30
41
|
}
|
|
31
42
|
function _batchActualVolume(b) {
|
|
@@ -66,6 +77,10 @@ function _trimBatch(b, formulationsById) {
|
|
|
66
77
|
measuredVolume: b.measuredVolume ?? null,
|
|
67
78
|
measuredVolumeUnit: b.measuredVolumeUnit || '',
|
|
68
79
|
actualVolume: _actualVolumeInfo(b),
|
|
80
|
+
// Actual MASS in kg (the conserved, additive quantity). From actual yield
|
|
81
|
+
// (mass-unit batch), else summed weighed inputs, else measured volume ×
|
|
82
|
+
// measured density. null when none is determinable.
|
|
83
|
+
actualMass: (function () { const m = _batchActualMassKg(b); return (m != null && isFinite(m)) ? { kg: +m.toFixed(4), unit: 'kg' } : null; })(),
|
|
69
84
|
preparedDate: b.preparedDate || '',
|
|
70
85
|
preparedBy: b.preparedBy || '',
|
|
71
86
|
process: b.process || '',
|
|
@@ -174,6 +189,11 @@ const get_batch = {
|
|
|
174
189
|
..._trimBatch(b, indexes.formulationsById),
|
|
175
190
|
notes: b.notes || '',
|
|
176
191
|
equipmentUsed: b.equipmentUsed || '',
|
|
192
|
+
// Multi-select equipment: full list [{name, equipmentId}]; falls back to
|
|
193
|
+
// the legacy single equipmentUsed so older batches still report one item.
|
|
194
|
+
equipmentUsedList: (Array.isArray(b.equipmentUsedList) && b.equipmentUsedList.length)
|
|
195
|
+
? b.equipmentUsedList.filter(e => e && e.name).map(e => ({ name: e.name, equipmentId: e.equipmentId || null }))
|
|
196
|
+
: (b.equipmentUsed ? [{ name: b.equipmentUsed, equipmentId: b.equipmentUsedId || null }] : []),
|
|
177
197
|
actualCompositionRowCount: Array.isArray(b.actualComposition) ? b.actualComposition.length : 0,
|
|
178
198
|
hasActualComposition: Array.isArray(b.actualComposition) && b.actualComposition.length > 0,
|
|
179
199
|
sourceBlendParents: parents,
|