formlab-mcp 0.6.58 → 0.6.59
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/package.json +1 -1
- package/server.json +2 -2
- package/tools/analytics.js +13 -2
- package/vendor/cost.js +2 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "formlab-mcp",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.59",
|
|
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
|
"homepage": "https://formvix.com/mcp",
|
package/server.json
CHANGED
|
@@ -2,13 +2,13 @@
|
|
|
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 server for FormLab formulation data: a local export file or your live cloud workspace.",
|
|
5
|
-
"version": "0.6.
|
|
5
|
+
"version": "0.6.59",
|
|
6
6
|
"websiteUrl": "https://formvix.com/mcp",
|
|
7
7
|
"packages": [
|
|
8
8
|
{
|
|
9
9
|
"registryType": "npm",
|
|
10
10
|
"identifier": "formlab-mcp",
|
|
11
|
-
"version": "0.6.
|
|
11
|
+
"version": "0.6.59",
|
|
12
12
|
"runtimeHint": "npx",
|
|
13
13
|
"transport": {
|
|
14
14
|
"type": "stdio"
|
package/tools/analytics.js
CHANGED
|
@@ -123,7 +123,7 @@ function _trimMeasurement(m, t, db) {
|
|
|
123
123
|
binCount: Array.isArray(m.bins) ? m.bins.length : 0,
|
|
124
124
|
...complex,
|
|
125
125
|
acceptanceCriteria: m.acceptanceCriteria || null,
|
|
126
|
-
// Effective spec + where it came from (override | template | parameter | none)
|
|
126
|
+
// Effective spec + where it came from (override | template | parameter | result: a Pass / Fail text result judged as written | none)
|
|
127
127
|
// and the app's pass/fail verdict under it.
|
|
128
128
|
...(() => { const r = _resolveSpec(m, t && t.templateId, db); return { effectiveSpec: r.spec || null, specSource: r.source, passFail: _evalPassFail(m, t && t.templateId, db) }; })(),
|
|
129
129
|
// Captured run conditions this reading was measured under (e.g.
|
|
@@ -822,8 +822,19 @@ function _resolveSpec(m, templateId, db) {
|
|
|
822
822
|
const lib = (store.parameters || []).find(p => p && p.id === m.parameterId);
|
|
823
823
|
if (lib && lib.acceptanceCriteria) return { spec: lib.acceptanceCriteria, source: 'parameter' };
|
|
824
824
|
}
|
|
825
|
+
// As the app (24b): no spec anywhere, a text result that is itself a verdict (Pass / Fail) is judged as written.
|
|
826
|
+
if (_measType(m) === 'categorical' && /^(pass|fail)$/.test(_catNorm(m.value))) return { spec: { requiredValue: 'pass', fromResult: true }, source: 'result' };
|
|
825
827
|
return { spec: null, source: 'none' };
|
|
826
828
|
}
|
|
829
|
+
// Text results, as the app (js/views/testing.js, 24b): a spec may accept several results
|
|
830
|
+
// ("=Clear | Slightly hazy"); Pass / Passed and Fail / Failed read as one word each.
|
|
831
|
+
function _catNorm(v) {
|
|
832
|
+
const s = String(v == null ? '' : v).trim().toLowerCase();
|
|
833
|
+
return /^pass(ed)?$/.test(s) ? 'pass' : /^fail(ed)?$/.test(s) ? 'fail' : s;
|
|
834
|
+
}
|
|
835
|
+
function _catPasses(required, value) {
|
|
836
|
+
return String(required == null ? '' : required).split('|').map(_catNorm).filter(Boolean).includes(_catNorm(value));
|
|
837
|
+
}
|
|
827
838
|
|
|
828
839
|
const _MEAS_TYPES = ['scalar', 'ordinal', 'categorical', 'time_series', 'distribution'];
|
|
829
840
|
function _measType(m) {
|
|
@@ -867,7 +878,7 @@ function _evalPassFail(m, templateId, db) {
|
|
|
867
878
|
if (type === 'categorical') {
|
|
868
879
|
if (!raw) return 'untested';
|
|
869
880
|
if (!crit.requiredValue) return 'no-criteria';
|
|
870
|
-
return
|
|
881
|
+
return _catPasses(crit.requiredValue, raw) ? 'pass' : 'fail';
|
|
871
882
|
}
|
|
872
883
|
// As the app (12y): one representative value against the range — a curve's
|
|
873
884
|
// FINAL point, a distribution's statistic named by the spec (crit.stat:
|
package/vendor/cost.js
CHANGED
|
@@ -1993,7 +1993,7 @@ function renderWeighoutPanel(w, actuals, formula, copyOnclick, noun) {
|
|
|
1993
1993
|
const _woVolTarget = (typeof isVolUnit === 'function') && isVolUnit(w.unit);
|
|
1994
1994
|
const qsTag = r => (!r.qs) ? '' :
|
|
1995
1995
|
` <span style="font-size:9.5px;color:var(--dk-sky-fg, #0369a1);font-weight:600;background:var(--dk-blue-bg, #eff6ff);border:1px solid var(--dk-blue-line, #bfdbfe);border-radius:4px;padding:0 3px;vertical-align:middle;white-space:nowrap" title="${_woVolTarget ? `Balance ingredient — add it up to the ${w.qty} ${esc(w.unit)} mark rather than to this number, then log what actually went in` : 'Balance ingredient, set to hold the batch at its target size'}">${_woVolTarget ? `q.s. to ${w.qty} ${esc(w.unit)}` : 'q.s.'}</span>`;
|
|
1996
|
-
const dColor = rel => rel == null ? '#94a3b8' : (rel < 0.02 ? '#15803d' : rel < 0.10 ? '#b45309' : '#b91c1c');
|
|
1996
|
+
const dColor = rel => rel == null ? 'var(--dk-faint, #94a3b8)' : (rel < 0.02 ? 'var(--dk-green-fg, #15803d)' : rel < 0.10 ? 'var(--dk-amber-fg, #b45309)' : 'var(--dk-red-fg, #b91c1c)');
|
|
1997
1997
|
// Tint a whole row when it deviates, so off-plan ingredients pop at a glance
|
|
1998
1998
|
// (matches the composition-% table's row tinting). On-target rows stay white.
|
|
1999
1999
|
const dRowBg = rel => (rel == null || rel < 0.02) ? '' : (rel < 0.10 ? 'background:var(--dk-amber-bg, #fffbeb)' : 'background:var(--dk-red-bg, #fef2f2)');
|
|
@@ -2590,7 +2590,7 @@ function entityCostValueHtml(o) {
|
|
|
2590
2590
|
const msg = (why === 'needs-density')
|
|
2591
2591
|
? `⚠ add a density to the formula to price ${esc(o.unit || 'this unit')} by mass`
|
|
2592
2592
|
: `can't convert ${esc(o.unit || 'this unit')} to mass`;
|
|
2593
|
-
const col = (why === 'needs-density') ? '#b45309' : 'var(--text-muted)';
|
|
2593
|
+
const col = (why === 'needs-density') ? 'var(--dk-amber-fg, #b45309)' : 'var(--text-muted)';
|
|
2594
2594
|
return `<span style="color:var(--text-muted)">—</span> <span style="font-size:11px;color:${col}">${msg}</span>${editBtn}`;
|
|
2595
2595
|
}
|
|
2596
2596
|
const breakdown = `<span style="font-size:11px;color:var(--text-muted);margin-left:6px">${esc(String(o.qty))} ${esc(o.unit || '')} × ${money(perKg)}/kg</span>`;
|