mathjs expressions, unit conversion and BigNumber precision: working versions (tested 2026-10-15)
Evaluate user formulas safely with mathjs: scoped and compiled expressions, unit conversions, matrices, a BigNumber instance for exact decimals, and disabling risky functions.
passed6 passed · 0 failed2026-10-15 17:11 UTC- Status
- passed
- Last passed
- 2026-10-15 17:11 UTC
- Tests
- 6 / 6
- Language
- TypeScript
- Runtime
- node v22.23.3
pinned versions3
mathjs@15.2.0@types/node@26.6.5tsx@4.23.15
run it
npm install --no-audit --no-fund --ignore-scripts=false npm test
test environment
node v22.23.3 linux 6.17.0-1022-azure x64 runner: github-actions 38775053802
The code
Exactly the files that passed. Your agent can pull them with get_recipe("mathjs-units-expressions") (install), or see them on GitHub.
package.json
{
"name": "mathjs-units-expressions",
"private": true,
"type": "module",
"scripts": {
"test": "node --import tsx --test test/*.test.ts"
},
"dependencies": {
"mathjs": "15.2.0"
},
"devDependencies": {
"@types/node": "26.6.5",
"tsx": "4.23.15"
}
}
src/calc.ts
import { create, all } from "mathjs";
/** Number-based instance with import and createUnit disabled, for evaluating untrusted formulas. */
export const math = create(all);
const limitedEvaluate = math.evaluate;
math.import(
{
import: () => { throw new Error("Function import is disabled"); },
createUnit: () => { throw new Error("Function createUnit is disabled"); },
},
{ override: true },
);
export const big = create(all, { number: "BigNumber", precision: 40 });
export function evalFormula(expr: string, scope: Record<string, number> = {}): number {
const r = limitedEvaluate(expr, { ...scope });
if (typeof r !== "number") throw new Error(`expected a number, got ${math.typeOf(r)}`);
return r;
}
export function convert(value: string, to: string, digits = 4): number {
return Number(math.unit(value).toNumber(to).toFixed(digits));
}
export function compileRule(expr: string) {
const code = math.compile(expr);
return (scope: Record<string, number>) => code.evaluate({ ...scope }) as number;
}
export function exactSum(values: string[]): string {
return big.format(values.reduce((s, v) => big.add(s, big.bignumber(v)), big.bignumber(0)));
}
test/calc.test.ts
import { test } from "node:test";
import assert from "node:assert/strict";
import { math, big, evalFormula, convert, compileRule, exactSum } from "../src/calc.ts";
test("evaluates formulas with a scope", () => {
assert.equal(evalFormula("price * qty * (1 - discount)", { price: 20, qty: 3, discount: 0.25 }), 45);
assert.equal(evalFormula("sqrt(16) + 2^3"), 12);
assert.throws(() => evalFormula("[1, 2]"), /expected a number, got DenseMatrix/);
});
test("converts units", () => {
assert.equal(convert("5 km", "mi"), 3.1069);
assert.equal(convert("100 degF", "degC", 2), 37.78);
assert.equal(math.evaluate("2 inch to cm").toString(), "5.08 cm");
});
test("compiled rules run repeatedly", () => {
const shipping = compileRule("weight > 10 ? 15 : 5 + weight * 0.5");
assert.equal(shipping({ weight: 4 }), 7);
assert.equal(shipping({ weight: 12 }), 15);
});
test("matrices", () => {
const m = math.matrix([[1, 2], [3, 4]]);
assert.equal(math.det(m), -2);
assert.deepEqual(math.multiply(m, [1, 1]).toArray(), [3, 7]);
});
test("BigNumber avoids float drift", () => {
assert.notEqual(0.1 + 0.2, 0.3);
assert.equal(exactSum(["0.1", "0.2"]), "0.3");
assert.equal(big.format(big.evaluate("1 / 3"), { precision: 10 }), "0.3333333333");
});
test("import and createUnit are disabled for untrusted input", () => {
assert.throws(() => math.evaluate('import({x: 1})'), /disabled/);
assert.throws(() => math.evaluate('createUnit("foo")'), /disabled/);
});
Connect to ProvenPin
Add the free MCP server so your agent can pull this recipe and others like it. Same setup as the docs.
terminal
claude mcp add --transport http provenpin https://mcp.provenpin.com/mcp
~/.cursor/mcp.json
{ "mcpServers": { "provenpin": { "url": "https://mcp.provenpin.com/mcp" } } }.vscode/mcp.json
{ "servers": { "provenpin": { "type": "http", "url": "https://mcp.provenpin.com/mcp" } } }~/.codeium/windsurf/mcp_config.json
{ "mcpServers": { "provenpin": { "serverUrl": "https://mcp.provenpin.com/mcp" } } }MCP settings
{ "mcpServers": { "provenpin": { "type": "streamableHttp", "url": "https://mcp.provenpin.com/mcp" } } }Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.