# Sagemath Mcp

> Sage Math MCP server for sateful sessions

- **Type:** MCP server
- **Install:** `agentstack add mcp-xbp-europe-sagemath-mcp`
- **Verified:** Pending review
- **Seller:** [XBP-Europe](https://agentstack.voostack.com/s/xbp-europe)
- **Installs:** 0
- **Category:** [Integrations](https://agentstack.voostack.com/c/integrations)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [XBP-Europe](https://github.com/XBP-Europe)
- **Source:** https://github.com/XBP-Europe/sagemath-mcp

## Install

```sh
agentstack add mcp-xbp-europe-sagemath-mcp
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# SageMath MCP Server

[](https://github.com/XBP-Europe/sagemath-mcp/actions/workflows/ci.yml)
[](https://github.com/XBP-Europe/sagemath-mcp/releases/latest)
[](https://pypi.org/project/sagemath-mcp/)
[](https://github.com/XBP-Europe/sagemath-mcp/pkgs/container/sagemath-mcp)
[](LICENSE)
[](https://www.python.org/downloads/)
[](https://modelcontextprotocol.io/)
[](https://gofastmcp.com/)
[](https://www.sagemath.org/)
[](https://docs.astral.sh/ruff/)
[](https://peps.python.org/pep-0561/)

A universal mathematics [Model Context Protocol](https://modelcontextprotocol.io/) (MCP) server that gives LLM clients full access to [SageMath](https://www.sagemath.org/) --- one of the most comprehensive open-source mathematics systems available. Built on [FastMCP 3.x](https://gofastmcp.com/), the server maintains a dedicated SageMath process for each MCP session so variables, functions, and assumptions persist across tool calls.

Whether the task is symbolic calculus, number theory, linear algebra, differential equations, plotting, combinatorics, graph theory, group theory, or basic arithmetic, the server provides **33 MCP tools** --- all math tools backed by the full SageMath engine, plus `evaluate_sage_streaming` (streaming wrapper) and an HTTP `/health` endpoint.

---

## Table of Contents

- [Features at a Glance](#features-at-a-glance)
- [Architecture Overview](#architecture-overview)
- [Quick Start](#quick-start)
- [Detailed Tool Reference](#detailed-tool-reference)
  - [evaluate_sage --- Open-Ended Execution](#evaluate_sage----open-ended-sagemath-execution)
  - [Calculus Tools](#calculus-tools)
  - [Algebra & Simplification Tools](#algebra--simplification-tools)
  - [Linear Algebra Tools](#linear-algebra-tools)
  - [Differential Equations](#differential-equations)
  - [Number Theory](#number-theory)
  - [Statistics](#statistics)
  - [Visualization](#visualization)
  - [Session Management & Observability](#session-management--observability)
- [Security Sandbox](#security-sandbox)
- [LLM Client Configuration](#llm-client-configuration)
- [Deployment](#deployment)
- [Configuration Reference](#configuration-reference)
- [CLI Reference](#cli-reference)
- [Development](#development)
- [CLI Integration Testing](#cli-integration-testing)
- [Project Layout](#project-layout)
- [Technology Stack](#technology-stack)
- [Changelog](#changelog)
- [Roadmap](#roadmap)
- [Contributing](#contributing)

---

## Features at a Glance

| Category | Tools | Backend | Capabilities |
|----------|-------|---------|-------------|
| **Core execution** | `evaluate_sage`, `evaluate_sage_streaming` | Sage | Run any SageMath code with persistent state, LaTeX output, stdout capture, progress heartbeats, per-call timeouts, and line-by-line streaming |
| **Calculus** | `differentiate_expression`, `integrate_expression`, `limit_expression`, `series_expansion` | Sage | Derivatives of any order, indefinite & definite integrals, one-sided limits, Taylor/Laurent series |
| **Algebra** | `solve_equation`, `simplify_expression`, `expand_expression`, `factor_expression`, `calculate_expression` | Sage | Single equations & systems, symbolic simplification, expansion, factoring, numeric evaluation |
| **Symbolic sums** | `symbolic_sum` | Sage | Symbolic summation and products (finite and infinite series) |
| **Linear algebra** | `matrix_multiply`, `matrix_operation` | Sage | Matrix products, determinants, inverses, eigenvalues, rank, RREF, transpose |
| **Differential equations** | `solve_ode` | Sage | First- and higher-order ODEs via Sage's `desolve()` |
| **Number theory** | `number_theory_operation` | Sage | Primality testing, integer factorization, next prime, GCD, LCM |
| **Combinatorics** | `combinatorics_operation` | Sage | Binomial, permutations, combinations, partitions, factorial, Catalan, Fibonacci, Bell numbers |
| **Graph theory** | `graph_operation` | Sage | Named graphs and adjacency dicts; chromatic number, connectivity, planarity, diameter, shortest path |
| **Group theory** | `group_operation` | Sage | Symmetric, dihedral, cyclic, alternating groups; order, abelian/cyclic test, center, exponent |
| **Elliptic curves** | `elliptic_curve_operation` | Sage | Rank, torsion, discriminant, j-invariant, conductor, generators |
| **Coding theory** | `coding_theory_operation` | Sage | Hamming, Reed-Solomon codes; length, dimension, minimum distance, generator matrix, rate |
| **Polynomial rings** | `polynomial_ring_operation` | Sage | Groebner bases, ideal dimension/variety, reduction, Groebner test |
| **Boolean algebra** | `boolean_algebra_operation` | Sage | Boolean polynomial ring; evaluate, variables, degree, zero/one test |
| **Geometry** | `geometry_operation` | Sage | Distance, polygon area, polytope volume, convex hull, compactness via `Polyhedron` |
| **Statistics** | `statistics_summary` | Sage | Mean, median, population & sample variance/std dev, min, max |
| **Probability** | `distribution_operation` | Sage | Normal, exponential, Poisson, chi-squared, Student-t, uniform, beta, gamma; PDF, CDF, quantile, sampling |
| **Visualization** | `plot_expression`, `plot3d_expression`, `plot_multi_expression` | Sage | 2D plots, 3D surface plots, multi-function overlays as base64-encoded PNG |
| **Numeric methods** | `find_root` | Sage | Numeric root-finding in an interval via Sage's `find_root()` |
| **Vector calculus** | `vector_calculus_operation` | Sage | Gradient, divergence, curl, Laplacian on scalar/vector fields |
| **Session control** | `reset_sage_session`, `cancel_sage_session` | Worker | Clear state or abort long-running computations |
| **Infrastructure** | `/health` endpoint, 3 MCP resources | Server | Health check, session snapshots, aggregated metrics, documentation links |

---

## Architecture Overview

```
┌──────────────────────────────────────────────────────────────────┐
│  MCP Client (Claude Desktop, Gemini CLI, Codex CLI, etc.)       │
└──────────────────────┬───────────────────────────────────────────┘
                       │  MCP protocol (stdio or HTTP)
                       ▼
┌──────────────────────────────────────────────────────────────────┐
│  server.py --- FastMCP 3.x Application                          │
│                                                                  │
│  ┌─────────────┐  ┌──────────────┐  ┌────────────────────────┐  │
│  │ 18 MCP Tools│  │ 3 Resources  │  │ Middleware              │  │
│  │ (evaluate,  │  │ (session,    │  │ - Request logging       │  │
│  │  solve,     │  │  monitoring, │  │ - Response caching      │  │
│  │  diff, ...)│  │  docs)       │  │ - Progress heartbeats   │  │
│  └──────┬──────┘  └──────────────┘  └────────────────────────┘  │
│         │                                                        │
│  ┌──────▼──────────────────────────────────────────────────────┐ │
│  │ session.py --- SageSessionManager                           │ │
│  │  Per-client session map with asyncio locks, idle culling    │ │
│  │  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐        │ │
│  │  │ Session A   │  │ Session B   │  │ Session C   │  ...   │ │
│  │  └──────┬──────┘  └──────┬──────┘  └──────┬──────┘        │ │
│  └─────────┼───────────────┼───────────────┼──────────────────┘ │
└────────────┼───────────────┼───────────────┼────────────────────┘
             │               │               │
             ▼               ▼               ▼
     ┌───────────────────────────────────────────────┐
     │  _sage_worker.py --- Subprocess Workers       │
     │  JSON stdin/stdout protocol                    │
     │                                                │
     │  ┌────────────┐   ┌──────────────────────┐    │
     │  │ security.py│──▶│ AST validation       │    │
     │  │            │   │ before every exec()   │    │
     │  └────────────┘   └──────────────────────┘    │
     │                                                │
     │  Persistent namespace: vars, functions,        │
     │  classes survive across calls                   │
     └────────────────────────────────────────────────┘
```

**Request flow:** MCP client → `server.py` tool → `SageSessionManager.get_or_create()` → `SageSession.evaluate()` → JSON request to `_sage_worker.py` subprocess → AST validation → `exec()` in persistent namespace → JSON response back.

**Key design decisions:**

- **Process isolation:** Each session runs SageMath in a separate subprocess. A crash or timeout in one session cannot affect others.
- **Stateful sessions:** Variables, functions, and assumptions persist across tool calls within the same MCP session, enabling multi-step mathematical workflows.
- **Security by default:** Every code snippet passes through an AST-based validator before execution, blocking dangerous operations regardless of the tool used.
- **Progress heartbeats:** Long-running computations emit periodic progress events (~1.5s) so clients can display activity indicators and detect stalls.

---

## Quick Start

### Install from PyPI

```bash
pip install sagemath-mcp

# Run the server over stdio (default)
sagemath-mcp

# Or expose an HTTP endpoint
sagemath-mcp --transport streamable-http --host 127.0.0.1 --port 8314
```

If the command is not on your `PATH`, run `python -m sagemath_mcp.server --help`.

### Develop from source

```bash
git clone https://github.com/XBP-Europe/sagemath-mcp.git
cd sagemath-mcp

# Install dependencies (use uv or pip)
uv pip install -e .[dev]

# Run the server over stdio (default)
uv run sagemath-mcp

# Run with streaming-friendly HTTP transport
uv run sagemath-mcp --transport streamable-http --host 127.0.0.1 --port 8314
```

### Optional: start a Sage container automatically

If you'd like a ready-to-use Sage runtime without installing it locally, run:

```bash
make sage-container  # or ./scripts/setup_sage_container.sh
```

On Windows PowerShell:

```powershell
pwsh -File scripts/setup_sage_container.ps1
```

### Docker Image

Build a ready-to-run container with the MCP server baked in:

```bash
docker build -t sagemath-mcp:latest .
docker run -p 8314:8314 sagemath-mcp:latest --transport streamable-http
```

Released images are published to `ghcr.io/xbp-europe/sagemath-mcp` and signed with Cosign.
Verify a downloaded artifact with:

```bash
cosign verify ghcr.io/xbp-europe/sagemath-mcp:latest \
  --certificate-identity "https://github.com/XBP-Europe/sagemath-mcp/.github/workflows/release.yml@refs/tags/vX.Y.Z" \
  --certificate-oidc-issuer "https://token.actions.githubusercontent.com"
```

### Docker Compose

```bash
docker compose up --build
```

The compose service exposes port `8314` on both host and container and mounts the repository at `/workspace`. Containers run as the non-root `sage` user (UID/GID 1000) to match the base image. Tweak runtime settings by editing the environment block (for example, increase `SAGEMATH_MCP_EVAL_TIMEOUT` or adjust `SAGEMATH_MCP_MAX_STDOUT`) before launch.

---

## Detailed Tool Reference

### `evaluate_sage` --- Open-Ended SageMath Execution

The primary tool. Executes arbitrary SageMath code inside a persistent worker process. Variables, functions, classes, and assumptions defined in one call survive into subsequent calls within the same MCP session.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `code` | `string` | *required* | SageMath code to execute. Multi-line strings are supported. |
| `want_latex` | `bool` | `false` | When `true`, the server generates a LaTeX representation of the final expression result (if one exists) via Sage's `latex()` function. Returned in the `latex` field. |
| `capture_stdout` | `bool` | `true` | When `true`, any output from `print()` statements is captured and returned in the `stdout` field. Set to `false` for faster execution when stdout is not needed. |
| `timeout` | `float` | `null` | Override the per-evaluation timeout in seconds. If omitted, the global default (`SAGEMATH_MCP_EVAL_TIMEOUT`, 30 s) applies. Must be > 0. |

**Returns** an `EvaluateResult` object:

| Field | Type | Description |
|-------|------|-------------|
| `result_type` | `"expression"` or `"statement"` | `"expression"` when the code ends with an expression whose value is captured; `"statement"` when it ends with an assignment or side effect. |
| `result` | `string` or `null` | The `repr()` of the final expression value, or `null` for statement-type code. |
| `latex` | `string` or `null` | LaTeX representation of the result (only when `want_latex=true` and the result is non-null). |
| `stdout` | `string` | Captured stdout output (empty string if nothing was printed or `capture_stdout=false`). Truncated to `SAGEMATH_MCP_MAX_STDOUT` characters. |
| `elapsed_ms` | `float` | Wall-clock execution time in milliseconds. |

**Behavior details:**

- While code is running, the server emits **progress heartbeats** roughly every 1.5 seconds so clients can display activity indicators.
- If the evaluation exceeds the timeout, the worker process is restarted and a `TimeoutError` is raised. All session state from prior calls is lost.
- If the startup code (`from sage.all import *` by default) failed when the worker launched, every subsequent `evaluate_sage` call returns a clear `StartupError` instead of a confusing NameError.
- The AST security validator runs on every code snippet before execution (see [Security Sandbox](#security-sandbox)).

**Domain-specific examples** (these are included in the tool description LLMs see):

| Domain | Example Sage code |
|--------|------------------|
| Combinatorics | `binomial(10, 3)`, `Permutations(4).cardinality()`, `Combinations([1,2,3,4], 2).list()` |
| Graph theory | `G = graphs.PetersenGraph(); G.chromatic_number()` |
| Number theory | `prime_range(100)`, `euler_phi(60)`, `continued_fraction(pi, nterms=10)` |
| Geometry | `polytopes.cube().volume()`, `EllipticCurve([0,0,1,-1,0]).rank()` |
| Probability | `RealDistribution('gaussian', 1).cum_distribution_function(1.96)` |
| Group theory | `SymmetricGroup(5).order()`, `AlternatingGroup(4).is_abelian()` |
| Polynomial rings | `R. = PolynomialRing(QQ); (a+b)^3` |
| Coding theory | `codes.HammingCode(GF(2), 3).minimum_distance()` |

**Stateful multi-step workflow:**

```
> evaluate_sage(code="var('a'); f = (a + 1)^5")
  result_type: "statement", result: null

> evaluate_sage(code="expand(f)")
  result_type: "expression", result: "a^5 + 5*a^4 + 10*a^3 + 10*a^2 + 5*a + 1"

> evaluate_sage(code="diff(f, a, 2)")
  result_type: "expression", result: "20*(a + 1)^3"
```

---

### Calculus Tools

#### `differentiate_expression`

Compute the symbolic derivative of an expression. Calls Sage's `diff(expr, var, order)` internally.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `expression` | `string` | *required* | The expression to differentiate (e.g. `"sin(x)*e^x"`, `"x^3 + 2*x"`). |
| `variable` | `string` | `"x"` | The variable to differentiate with respect to. |
| `order` | `int` (>= 1) | `1` | Differentiation order. `1` = first derivative, `2` = second derivative, etc. |

**Returns:** `{"derivative": "...", "order": N}`

```
> differentiate_expression(expression="x^5", variable="x", order=3)
  {"derivative": "60*x^2", "order": 3}

> differentiate_expression(expression="sin(x)*cos(x)")
  {"derivative": "cos(x)^2 - sin(x)^2", "order": 1}
```

#### `integrate_expression`

Compute indefinite or definite integrals. Calls Sage's `integrate()` function.

| Parameter | Type | Default | Description |
|-----------|------|---------|-------------|
| `expression` | `string` | *required* | The expression to integrate. |
| `variable` | `string` | `"x"` | The integration variable. |
| `lower_bound` | `string` or `null` | `null` | Lower bound for definite integrals. Accepts symbolic values like `"0"`, `"-oo"` (negative infinity), or expressions like `"-pi"`. |
| `upper_bound` | `string` or `null` | `null` | Upper bound for definite integrals. Accepts `"1"`, `"oo"` (infinity), `"pi/2"`, etc. |

Bot

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [XBP-Europe](https://github.com/XBP-Europe)
- **Source:** [XBP-Europe/sagemath-mcp](https://github.com/XBP-Europe/sagemath-mcp)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** yes
- **Shell / process execution:** yes
- **Environment & secrets:** no
- **Dynamic code execution:** yes

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: flagged — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-xbp-europe-sagemath-mcp
- Seller: https://agentstack.voostack.com/s/xbp-europe
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
