safe-mathjs-mcp

safe-mathjs-mcp

Safe MCP server for math operations: evaluate, simplify, and differentiate expressions with configurable precision, using a sandboxed worker thread and strict AST allowlist to block dangerous input.

Category
Visit Server

README

safe-mathjs-mcp

A sandboxed math MCP server for Node.js. It gives LLM agents a safe place to evaluate, simplify, and differentiate mathematical expressions — powered by mathjs.

Why "safe"? Untrusted model input is evaluated inside a worker thread against a strict AST allowlist: only pure functions over numbers and number-matrices, no eval, no string processing, no assignments, no accessors, no units, no randomness — with a hard execution timeout.

Tools

Tool Description
evaluate Evaluate a numeric expression. Supports variables and configurable precision.
simplify Symbolic simplification (collect like terms, fold constants). Free symbols stay symbolic.
derivative Symbolic differentiation with respect to a variable.

Quick start

Requires Node.js >= 18.

npm install
npm start            # run the stdio server directly
npm run inspect      # interactive testing via the MCP inspector

To connect the server to an agent harness (Claude Desktop, Claude Code, Zed, VS Code, ...), see Installing in agent harnesses.

Installing in agent harnesses

The server speaks MCP over stdio, so every harness works the same way: it spawns node with the entry script. Prerequisites: npm install has been run in the repo, Node.js >= 18 is on PATH, and you use an absolute path to the repo (replace /path/to/safe-mathjs-mcp below). The working directory doesn't matter — the worker script and mathjs resolve relative to the entry file.

The universal entry, reused below in each harness's format:

{
  "mcpServers": {
    "safe-mathjs": {
      "command": "node",
      "args": ["/path/to/safe-mathjs-mcp/src/index.js"]
    }
  }
}

Claude Desktop

Edit the config file — ~/Library/Application Support/Claude/claude_desktop_config.json (macOS), %APPDATA%\Claude\claude_desktop_config.json (Windows), or ~/.config/Claude/claude_desktop_config.json (Linux) — and add the universal mcpServers entry from above. Restart Claude Desktop afterwards.

Claude Code

Add it from the CLI (no config file needed):

claude mcp add safe-mathjs -- node /path/to/safe-mathjs-mcp/src/index.js
claude mcp list          # verify

By default this applies to your user account; use --scope project to scope it to the current project or --scope local for your local machine only. Alternatively, commit a .mcp.json in the project root with the same mcpServers shape.

Zed

Add an mcp key (note: Zed uses mcp, not mcpServers) to ~/.config/zed/settings.json:

{
  "mcp": {
    "safe-mathjs": {
      "command": "node",
      "args": ["/path/to/safe-mathjs-mcp/src/index.js"],
      "enabled": true
    }
  }
}

Zed also accepts an environment object here if you want to pass CALC_TIMEOUT_MS.

VS Code (Copilot)

Create .vscode/mcp.json in your workspace. VS Code uses a servers key and an optional type field, which differs from most other harnesses:

{
  "servers": {
    "safe-mathjs": {
      "type": "stdio",
      "command": "node",
      "args": ["/path/to/safe-mathjs-mcp/src/index.js"]
    }
  }
}

Reload the window after adding it.

Cursor

Create .cursor/mcp.json in the project root with the same mcpServers shape as the Claude Desktop example above.

Cline

Add it through Cline's MCP settings (cline_mcp_settings.json, reachable from the Cline settings UI) — same mcpServers shape as Claude Desktop. Cline lets you set environment variables per server in the same JSON.

Any MCP SDK client

import { Client } from "@modelcontextprotocol/sdk/client/index.js";
import { StdioClientTransport } from "@modelcontextprotocol/sdk/client/stdio.js";

const transport = new StdioClientTransport({
  command: "node",
  args: ["/path/to/safe-mathjs-mcp/src/index.js"],
});
const client = new Client({ name: "my-app", version: "1.0.0" });
await client.connect(transport);

const { content } = await client.callTool({
  name: "evaluate",
  arguments: { expression: "2^10" },
});

Troubleshooting

  • Restart the harness after editing config files — most clients only load MCP servers at startup.
  • Wrong path / node not found — use the absolute repo path, and make sure node resolves for the harness's shell (check with node --version).
  • Passing env vars — harnesses that support an environment field (Zed, Cline) can set CALC_TIMEOUT_MS there. For clients that don't (e.g. Claude Desktop), wrap the command: env CALC_TIMEOUT_MS=5000 node /path/to/safe-mathjs-mcp/src/index.js.
  • Sanity check first — run npm run inspect in the repo to confirm the server starts and the tools respond before wiring it into a harness.

Tool reference

evaluate

  • expression (required) — math expression, max 512 chars. Example: 2 * (12 + sqrt(255))^2
  • precision (optional) — significant digits for the result, 1–100 (default 10)
  • variables (optional) — named numeric values, e.g. { x: 2 }
evaluate("5! + mean([1,2,3]) + det([[1,2],[3,4]])")   → 120
evaluate("x^2 + 1", { variables: { x: 3 } })           → 10
evaluate("1/3", { precision: 30 })                     → 0.333333333333333333333333333333

simplify

  • expression (required)
  • variables (optional) — known values folded in as constants
simplify("3*x + 2*x")       → 5 * x
simplify("x/x")             → 1
simplify("x^2 + 2*x + 1")   → x ^ 2 + 2 * x + 1

Note: simplification is heuristic — it collects like terms and folds constants but does not expand products or factor polynomials. Free symbols are treated as unknowns; e.g. x/x simplifies to 1, dropping the x != 0 case.

derivative

  • expression (required)
  • variable (required) — variable to differentiate with respect to, e.g. x
derivative("x^3 + sin(x)", "x")   → 3 * x ^ 2 + cos(x)
derivative("a*x^2 + b", "x")      → 2 * a * x
derivative("x^2", "y")            → 0

Other symbols in the expression are treated as free constants; the result is simplified.

Supported surface

Operators: + - * / ^ % ! and unary plus/minus

Constants: pi, e, tau

Functions (pure math over numbers and number-matrices):

Category Functions
Arithmetic & roots sqrt, cbrt, abs, pow, exp, log, ln, log10, log2, nthRoot, gcd, lcm, factorial, sign, hypot, mod
Trigonometry sin, cos, tan, asin, acos, atan, atan2, sinh, cosh, tanh
Rounding & min/max floor, ceil, round, min, max
Number theory isPrime, combinations, permutations
Statistics mean, median, std, sum, prod, variance, mode
Linear algebra det, inv, transpose, norm, dot, cross

Array literals like [1,2,3] and matrices like [[1,2],[3,4]] are supported for statistics and linear algebra.

Note: elementwise application of scalar functions to matrices (e.g. sqrt([4,9])) is not supported — write [sqrt(4), sqrt(9)] instead.

Security model

Expressions are untrusted model input, so evaluation happens in a dedicated worker thread behind layered guards:

  1. Worker isolation — evaluation runs in a worker thread; if an expression ever hangs, the thread is terminated (2 s timeout, configurable via CALC_TIMEOUT_MS). If the worker crashes, the next call respawns it.
  2. AST allowlist, not blocklist — the expression is parsed and every node validated before evaluation. Only these node types pass:
    • ConstantNode (numbers only — string/boolean/null literals are rejected)
    • SymbolNode (pi, e, tau, or declared variables)
    • OperatorNode (allowlisted operators)
    • FunctionNode (allowlisted functions)
    • ParenthesisNode, ArrayNode
  3. No code execution — mathjs is a pure AST interpreter; eval/new Function are never used, and the string-processing functions (evaluate, parse, compile, format, print) are not in the allowlist.
  4. Structural exclusions — assignments (x = 5), object literals, indexing (A[1]), conditionals (a ? b : c), ranges (1:5), multi-statement blocks, comparison/logical/bitwise operators, units, and randomness are all rejected with a Disallowed ... error.
  5. Result checks — complex numbers (scalar or inside arrays) and NaN are rejected after evaluation.
  6. Bounded input — expressions are capped at 512 characters; variables must be valid identifiers and prototype-polluting names (__proto__, constructor, prototype) are rejected.
  7. BigNumber precision — all math runs on BigNumber with configurable significant digits (default 10), avoiding float artifacts.

Anything outside this surface fails loudly with a descriptive error — nothing is silently coerced.

Configuration

Env var Default Purpose
CALC_TIMEOUT_MS 2000 Max wall-clock time for a single evaluation before the worker is terminated

Project layout

src/
  index.js              MCP server: tool registration, worker lifecycle, timeouts
  evaluator-worker.js   Sandbox: parsing, AST validation, whitelists, evaluation

Extending the whitelist

The allowlists live at the top of src/evaluator-worker.js (ALLOWED_FUNCTIONS, ALLOWED_OPERATORS, ALLOWED_SYMBOLS, ALLOWED_NODES). When adding a function, keep to the rule: pure, deterministic, numbers and number-matrices only. Functions that take strings, return units, or accept function-valued arguments (e.g. map, format, unit) do not fit the model. Verify the function exists in the installed mathjs version before adding (e.g. solve and nextPrime were removed in mathjs 13).

License

MIT

Recommended Servers

playwright-mcp

playwright-mcp

A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.

Official
Featured
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.

Official
Featured
Local
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.

Official
Featured
Local
TypeScript
VeyraX MCP

VeyraX MCP

Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.

Official
Featured
Local
Kagi MCP Server

Kagi MCP Server

An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.

Official
Featured
Python
graphlit-mcp-server

graphlit-mcp-server

The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.

Official
Featured
TypeScript
Neon Database

Neon Database

MCP server for interacting with Neon Management API and databases

Official
Featured
Exa Search

Exa Search

A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.

Official
Featured
Qdrant Server

Qdrant Server

This repository is an example of how to create a MCP server for Qdrant, a vector search engine.

Official
Featured
E2B

E2B

Using MCP to run code via e2b.

Official
Featured