ProvenPin Install

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

Any other MCP client: Streamable HTTP at https://mcp.provenpin.com/mcp. No API key, no signup.