Skip to content

Jsewill/math-mcp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

math-mcp

CI Coverage Python License: MIT

An MCP server that gives LLM agents exact, arbitrary-precision, and symbolic math. Backed by SymPy and mpmath, so 1/3 + 1/7 returns 10/21 — not 0.47619047619047616.

Every tool returns a typed Pydantic model, so MCP clients see structured output with a generated JSON schema — no re-parsing. Docstrings lead with USE THIS WHEN … to steer LLM tool routing.

Features

37 tools across seven domains:

Domain Tools
Arithmetic / numeric evaluate, evaluate_batch, numeric (up to 10,000 digits)
Algebra simplify, expand, factor, solve_equation, solve_inequality, solve_system, polynomial_roots, nroots
Calculus differentiate, integrate (definite & indefinite), limit, series, summation
Number theory gcd, lcm, factorint, is_prime, nth_prime, next_prime, mod_pow, mod_inverse
Combinatorics binomial, permutations, combinations
Linear algebra matrix_determinant, matrix_inverse, matrix_multiply, matrix_eigenvalues, matrix_solve
Conversions / stats stats, to_rational, to_base, from_base, convert_units

Safety

  • No eval. All inputs are parsed through SymPy's AST-based expression parser. Implicit multiplication is supported (2x parses as 2*x).
  • Input caps (see src/math_mcp/limits.py) reject pathological inputs before they reach SymPy: max 4096-char expressions, max 4096-bit integers, max 32×32 matrices, max 10,000 numeric digits, max 50-order series, max 20-order derivatives.
  • Typed error messages identify which limit was exceeded so callers can adjust.

Install

With uv / uvx (recommended)

uvx --from git+https://github.com/Jsewill/math-mcp sympy-math-mcp

or from a local checkout:

uv tool install .
sympy-math-mcp

With pip

pip install git+https://github.com/Jsewill/math-mcp
sympy-math-mcp

The PyPI distribution is named sympy-math-mcp (the bare math-mcp name belongs to an unrelated package). Once published, uvx sympy-math-mcp / pip install sympy-math-mcp will work without the git URL.

Register with Claude Code

claude mcp add math-mcp --scope user -- uvx --from git+https://github.com/Jsewill/math-mcp sympy-math-mcp

Or add to ~/.claude.json manually:

{
  "mcpServers": {
    "math-mcp": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/Jsewill/math-mcp", "sympy-math-mcp"]
    }
  }
}

Register with Claude Desktop

Edit ~/Library/Application Support/Claude/claude_desktop_config.json (macOS) or %APPDATA%\Claude\claude_desktop_config.json (Windows):

{
  "mcpServers": {
    "math-mcp": {
      "command": "uvx",
      "args": ["--from", "git+https://github.com/Jsewill/math-mcp", "sympy-math-mcp"]
    }
  }
}

Plugin: enforce routing (optional)

The MCP server ships in-context routing instructions, but those are persuasion — a stubborn agent can still shell out to python -c, bc, or $((...)). The plugin/ directory adds runtime enforcement:

  • PreToolUse:Bash hook — regex-detects shell calculator patterns (python -c, bc, dc, qalc, $((...)), node -e, expr, perl -e, awk 'BEGIN{print}') and nudges the model toward mcp__math-mcp__evaluate / evaluate_batch. Catches the "I'll just use bash" path.
  • UserPromptSubmit hook — when the user's prompt contains math signals (digits with operators, exponents, calculate / solve / integrate / …, percent-of, unit conversions, primality, stats, base conversions, matrix ops), injects a pre-response directive into context for that turn only requiring any derived number to come from a mcp__math-mcp__* call. Zero context cost on non-math turns.
  • SubagentStart hook — subagents don't inherit the parent session's UserPromptSubmit injection, so without this hook delegation (to Explore / Plan / custom agents) is an enforcement hole. Re-plants a short routing directive into every spawned subagent.
  • Skill (math-mcp) — phrase-triggered tool picker; loads only when it's needed.
  • Slash command (/math-verify) — post-hoc re-verification of every derived number in the last assistant turn.

Session-level routing rules arrive via the server's MCP instructions field, so no SessionStart hook is needed — it would just duplicate what the MCP server already ships.

Honest limit: no Claude Code hook fires on the assistant's prose output itself, so mental arithmetic that is embedded directly in text (no tool call, no shell fallback) cannot be blocked at inference time. The above hooks maximize pressure at every boundary the harness exposes (user prompt, tool call); the rest is the model's training-level reflex for tool use.

The detector is shared (Node ESM in plugin/core/detect_math.mjs; inlined into plugin/opencode/math-mcp.ts so the opencode install stays one file).

Claude Code

From this repo as a marketplace (recommended):

/plugin marketplace add Jsewill/math-mcp
/plugin install math-mcp@math-mcp

Or point Claude Code directly at the plugin directory:

claude plugin install /path/to/math-mcp/plugin

The plugin's manifest (plugin/.claude-plugin/plugin.json) also registers the MCP server, so installing the plugin replaces the claude mcp add step above.

opencode

Drop the single-file plugin into your opencode plugins dir and add math-mcp under mcp in your opencode.json:

# global (every opencode project)
cp plugin/opencode/math-mcp.ts ~/.config/opencode/plugins/math-mcp.ts
# or per-project
cp plugin/opencode/math-mcp.ts .opencode/plugins/math-mcp.ts

Merge plugin/opencode/opencode.json into your config to register the MCP server. Optionally copy plugin/opencode/AGENTS.md into project root for session-level routing rules.

Example tool calls

evaluate(expression="2**100 + 1")
  → exact: "1267650600228229401496703205377"

evaluate(expression="1/3 + 1/7 + 1/11")
  → exact: "131/231"

numeric(expression="pi", digits=60)
  → exact: "3.14159265358979323846264338327950288419716939937510582097494"

solve_equation(equation="x**2 - 2 = 0", domain="real")
  → solutions: ["-sqrt(2)", "sqrt(2)"]

solve_inequality(inequality="x**2 - 4 > 0", variable="x")
  → solution_set: "Union(Interval.open(-oo, -2), Interval.open(2, oo))"

polynomial_roots(polynomial="(x - 1)**2 * (x - 2)")
  → multiplicities: {"1": 2, "2": 1}

integrate(expression="1/(1+x**2)", variable="x", lower="0", upper="1")
  → exact: "pi/4"   (decimal: 0.7853981633974483…)

summation(expression="1/n**2", index="n", lower="1", upper="oo")
  → exact: "pi**2/6"

is_prime(number="2**521 - 1")
  → value: true    (Mersenne M_521)

mod_pow(base="7", exponent="2**100", modulus="10**9+7")
  → value: 641087921

binomial(n=52, k=5)
  → value: 2598960    (poker hands)

to_base(number="255", base=16)
  → digits: "ff"

convert_units(value="5", source_unit="meter", target_unit="foot")
  → converted: "6250/381 foot"   (decimal: 16.4041994750656)

Development

git clone https://github.com/Jsewill/math-mcp
cd math-mcp
uv sync --all-groups
uv run coverage run -m pytest
uv run coverage report

Coverage is enforced at 100% (fail_under = 100 in pyproject.toml); any regression breaks the test run.

Run the server directly (stdio transport):

uv run sympy-math-mcp

License

MIT — see LICENSE.

About

Exact, arbitrary-precision, symbolic math for LLM agents over MCP; 36 SymPy-backed tools with typed outputs.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors