Symbolic Algebra MCP Server
Provides symbolic mathematics tools backed by SymPy, enabling algebraic equation solving, integration, differentiation, vector and tensor calculus, ODE/PDE solving, simplification, substitution, factorization, expansion, limits, series expansions, and inequality solving.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Symbolic Algebra MCP Serversolve the equation x^2 - 5x + 6 = 0 for x"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Symbolic Algebra MCP Server (lag-sympy-mcp)
This is a maintained fork of sdiehl/sympy-mcp, which is no longer maintained upstream (Apache License 2.0). It adds algebra and calculus tools (factor_expression, expand_expression, cancel_expression, apart_expression, limit_expression, series_expansion, solve_inequality) and a safe expression parser; see MODIFICATIONS.md.
Sympy-MCP is a Model Context Protocol server for allowing LLMs to autonomously perform symbolic mathematics and computer algebra. It exposes numerous tools from SymPy's core functionality to MCP clients for manipulating mathematical expressions and equations.
Why?
Language models are absolutely abysmal at symbolic manipulation. They hallucinate variables, make up random constants, permute terms and generally make a mess. But we have computer algebra systems specifically built for symbolic manipulation, so we can use tool-calling to orchestrate a sequence of transforms so that the symbolic kernel does all the heavy lifting.
While you can certainly have an LLM generate Mathematica or Python code, if you want to use the LLM as an agent or on-the-fly calculator, it's a better experience to use the MCP server and expose the symbolic tools directly.
The server exposes a subset of symbolic mathematics capabilities including algebraic equation solving, integration and differentiation, vector calculus, tensor calculus for general relativity, and both ordinary and partial differential equations.
For example, you can ask it in natural language to solve a differential equation:
Solve the damped harmonic oscillator with forcing term: the mass-spring-damper system described by the differential equation where m is mass, c is the damping coefficient, k is the spring constant, and F(t) is an external force.
$$ m\frac{d^2x}{dt^2} + c\frac{dx}{dt} + kx = F(t) $$
Or involving general relativity:
Compute the trace of the Ricci tensor $R_{\mu\nu}$ using the inverse metric $g^{\mu\nu}$ for Anti-de Sitter spacetime to determine its constant scalar curvature $R$.
Related MCP server: mcp-sympy
Usage
You need uv first.
Homebrew :
brew install uvCurl :
curl -LsSf https://astral.sh/uv/install.sh | sh
Then you can install and run the server with the following commands:
# Setup the project
git clone https://github.com/laguchoritarik/lag-sympy-mcp.git
cd lag-sympy-mcp
uv sync
# Install the server to Claude Desktop
uv run mcp install server.py
# Run the server
uv run mcp run server.pyYou should see the server available in the Claude Desktop app now. For other clients, see below.
Claude Code setup
claude mcp add --scope user sympy-mcp -- uv --directory /ABSOLUTE_PATH_TO/lag-sympy-mcp run mcp run server.pyReplace /ABSOLUTE_PATH_TO/lag-sympy-mcp with the absolute path of your clone, then check the connection with claude mcp list.
If you want to do general relativity calculations, you need to install the einsteinpy library.
uv sync --group relativityAvailable Tools
The sympy-mcp server provides the following tools for symbolic mathematics:
Tool | Tool ID | Description |
Variable Introduction |
| Introduces a variable with specified assumptions and stores it |
Multiple Variables |
| Introduces multiple variables with specified assumptions simultaneously |
Expression Parser |
| Parses an expression string using available local variables and stores it |
LaTeX Printer |
| Prints a stored expression in LaTeX format, along with variable assumptions |
Algebraic Solver |
| Solves an equation algebraically for a given variable over a given domain |
Linear Solver |
| Solves a system of linear equations |
Nonlinear Solver |
| Solves a system of nonlinear equations |
Function Variable |
| Introduces a function variable for use in differential equations |
ODE Solver |
| Solves an ordinary differential equation |
PDE Solver |
| Solves a partial differential equation |
Standard Metric |
| Creates a predefined spacetime metric (e.g. Schwarzschild, Kerr, Minkowski) |
Metric Search |
| Searches available predefined metrics |
Tensor Calculator |
| Calculates tensors from a metric (Ricci, Einstein, Weyl tensors) |
Custom Metric |
| Creates a custom metric tensor from provided components and symbols |
Tensor LaTeX |
| Prints a stored tensor expression in LaTeX format |
Simplifier |
| Simplifies a mathematical expression using SymPy's canonicalize function |
Substitution |
| Substitutes a variable with an expression in another expression |
Integration |
| Integrates an expression with respect to a variable |
Differentiation |
| Differentiates an expression with respect to a variable |
Coordinates |
| Creates a 3D coordinate system for vector calculus operations |
Vector Field |
| Creates a vector field in the specified coordinate system |
Curl |
| Calculates the curl of a vector field |
Divergence |
| Calculates the divergence of a vector field |
Gradient |
| Calculates the gradient of a scalar field |
Unit Converter |
| Converts a quantity to given target units |
Unit Simplifier |
| Simplifies a quantity with units |
Matrix Creator |
| Creates a SymPy matrix from the provided data |
Determinant |
| Calculates the determinant of a matrix |
Matrix Inverse |
| Calculates the inverse of a matrix |
Eigenvalues |
| Calculates the eigenvalues of a matrix |
Eigenvectors |
| Calculates the eigenvectors of a matrix |
Factorization |
| Factors an expression over Q (optionally over Q(i) or GF(p)) |
Expansion |
| Expands products and integer powers of sums |
Rational Cancellation |
| Puts a rational expression in canonical form p/q with common factors cancelled |
Partial Fractions |
| Computes the partial fraction decomposition of a rational expression |
Limit |
| Computes a limit at a finite point or at ±∞ (two-sided or one-sided) |
Series Expansion |
| Computes a Taylor/Laurent expansion with or without the O(...) remainder |
Inequality Solver |
| Solves an inequality (or And/Or of inequalities) in one real variable |
By default variables are predefined with assumptions (similar to how the symbols() function works in SymPy). Unless otherwise specified the defaut assumptions is that a variable is complex, commutative, term over the complex field $\mathbb{C}$.
Property | Value |
| true |
| true |
| true |
| false |
Algebra and Calculus Tools
These tools work on expressions already stored with introduce_expression and return a new
expression key (print it with print_latex_expression), except solve_inequality, which returns
the LaTeX of the solution set, like solve_algebraically. factor_expression, expand_expression,
cancel_expression and apart_expression apply to both sides of an equation and to each entry of
a matrix.
Tool | Parameters | Example input → output |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Notes:
limit_expressionreports an error, rather than a value, when the limit does not exist: one-sided limits that differ (1/x,Abs(x)/xat 0) or oscillation (sin(x)atoo).Inequalities are solved over the reals. Write a double inequality
a < f(x) < basAnd(a < f(x), f(x) < b); Python's chained comparison is not supported by SymPy.The
pointarguments oflimit_expressionandseries_expansionare not passed toparse_expr. They are parsed with Python'sastmodule against an allow-list: numbers, introduced variables,oo/inf/infinity/zoo/pi/E/I,+ - * / ** ^, and the functionssqrt,exp,log,sin,cos,tan,Rational. Anything else (attribute access, subscripts, strings, keyword arguments, other calls, very large exact powers, inputs over 256 characters) is rejected before evaluation.
Claude Desktop Setup
Normally the mcp install command will automatically add the server to the claude_desktop_config.json file. If it doesn't you need to find the config file and add the following:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.json
Add the following to the mcpServers object, replacing /ABSOLUTE_PATH_TO_SYMPY_MCP/server.py with the absolute path to the sympy-mcp server.py file.
{
"mcpServers": {
"sympy-mcp": {
"command": "/opt/homebrew/bin/uv",
"args": [
"run",
"--with",
"einsteinpy",
"--with",
"mcp[cli]",
"--with",
"pydantic",
"--with",
"sympy",
"mcp",
"run",
"/ABSOLUTE_PATH_TO_SYMPY_MCP/server.py"
]
}
}
}Cursor Setup
In your ~/.cursor/mcp.json, add the following, where ABSOLUTE_PATH_TO_SYMPY_MCP is the path to the sympy-mcp server.py file.
{
"mcpServers": {
"sympy-mcp": {
"command": "/opt/homebrew/bin/uv",
"args": [
"run",
"--with",
"einsteinpy",
"--with",
"mcp[cli]",
"--with",
"pydantic",
"--with",
"sympy",
"mcp",
"run",
"/ABSOLUTE_PATH_TO_SYMPY_MCP/server.py"
]
}
}
}VS Code Setup
VS Code and VS Code Insiders now support MCPs in agent mode. For VS Code, you may need to enable Chat > Agent: Enable in the settings.
One-click Setup:
OR manually add the config to your settings.json (global):
{
"mcp": {
"servers": {
"sympy-mcp": {
"command": "uv",
"args": [
"run",
"--with",
"einsteinpy",
"--with",
"mcp[cli]",
"--with",
"pydantic",
"--with",
"sympy",
"mcp",
"run",
"/ABSOLUTE_PATH_TO_SYMPY_MCP/server.py"
]
}
}
}
}Click "Start" above the server config switch to agent mode in the chat, and try commands like "integrate x^2" or "solve x^2 = 1" to get started.
HTTP Transport (Streamable HTTP / SSE)
The server supports MCP over HTTP using the streamable-http transport introduced in MCP spec 2025-03-26. This replaces the legacy SSE transport and exposes a single /mcp endpoint that clients connect to over HTTP.
This is the recommended transport when running the server as a standalone process or in a container, because it allows any HTTP-capable MCP client to connect without needing to launch the server as a subprocess.
# Run locally with HTTP transport
uv run python server.py --transport streamable-http
# Override host/port
uv run python server.py --transport streamable-http --mcp-host 127.0.0.1 --mcp-port 9000The legacy --transport sse flag is still supported for backward compatibility.
A /healthcheck endpoint is also exposed that runs a full MCP protocol round-trip (initialize → tools/list → session teardown) and returns {"status": "ok", "tool_count": N}.
Running in Container
You can build and run the server using Docker locally:
# Build the Docker image
docker build -t sympy-mcp .
# Run the Docker container
docker run -p 8081:8081 sympy-mcpOr use Docker Compose from the docker/ directory:
cd docker
docker compose up -d --buildAlternatively, you can pull the pre-built image from GitHub Container Registry:
# Pull the latest image
docker pull ghcr.io/laguchoritarik/lag-sympy-mcp:main
# Run the container
docker run -p 8081:8081 --rm ghcr.io/laguchoritarik/lag-sympy-mcp:mainTo configure Claude Desktop to launch the Docker container, edit your claude_desktop_config.json file:
{
"mcpServers": {
"sympy-mcp": {
"command": "docker",
"args": [
"run",
"-i",
"-p",
"8081:8081",
"--rm",
"sympy-mcp"
]
}
}
}Or to use the pre-built container from GitHub:
{
"mcpServers": {
"sympy-mcp": {
"command": "docker",
"args": [
"run",
"-i",
"-p",
"8081:8081",
"--rm",
"ghcr.io/laguchoritarik/lag-sympy-mcp:main"
]
}
}
}This configuration tells Claude Desktop to launch the Docker container when needed. Make sure to build the Docker image (docker build -t sympy-mcp .) before using Claude Desktop with this configuration.
The other installation methods can also be adapted to work with Docker if you change the uv command to use the docker run command instead.
Example Interaction 1 : Differential Equations
Here's an example of how the tool-calling works in a conversation with an AI assistant using this MCP server:
User: Solve the damped harmonic oscillator with forcing term: the mass-spring-damper system described by the differential equation where m is mass, c is the damping coefficient, k is the spring constant, and F(t) is an external force.
$$ m\frac{d^2x}{dt^2} + c\frac{dx}{dt} + kx = F(t) $$
Assistant: (Internal tool call) intro_many to introduce variables:
{
"variables": [
{"var_name": "t", "pos_assumptions": ["real"], "neg_assumptions": []},
{"var_name": "m", "pos_assumptions": ["real", "positive"], "neg_assumptions": []},
{"var_name": "c", "pos_assumptions": ["real", "positive"], "neg_assumptions": []},
{"var_name": "k", "pos_assumptions": ["real", "positive"], "neg_assumptions": []}
]
}Assistant: (Internal tool call) introduce_function to define x(t):
{
"func_name": "x"
}Assistant: (Internal tool call) introduce_expression to create the differential equation:
{
"expr_str": "Eq(m*Derivative(x(t), t, t) + c*Derivative(x(t), t) + k*x(t), F(t))"
}Assistant: (Internal tool call) print_latex_expression to display the equation nicely:
{
"expr_key": "expr_12"
}Result:
$$ c \frac{d}{d t} x{\left(t \right)} + k x{\left(t \right)} + m \frac{d^{2}}{d t^{2}} x{\left(t \right)} = F{\left(t \right)} $$
Assistant: (Internal tool call) introduce_function to define F(t):
{
"func_name": "F"
}Assistant: (Internal tool call) dsolve_ode to solve the differential equation:
{
"expr_key": "expr_12",
"func_name": "x"
}Result:
$$ x{\left(t \right)} = C_{1} e^{\frac{t \left(- c + \sqrt{c^{2} - 4 k m}\right)}{2 m}} + C_{2} e^{- \frac{t \left(c + \sqrt{c^{2} - 4 k m}\right)}{2 m}} + \cdots $$
Example Interaction 2: General Relativity
User: Compute the trace of the Ricci tensor $R_{\mu\nu}$ using the inverse metric $g^{\mu\nu}$ for Anti-de Sitter spacetime to determine its constant scalar curvature $R$.
Assistant: (Internal tool call) create_predefined_metric to create the Anti-de Sitter metric:
{
"metric_name": "AntiDeSitter"
}Assistant: (Internal tool call) calculate_tensor to calculate the Ricci tensor:
{
"metric_key": "metric_AntiDeSitter",
"tensor_type": "RICCI_TENSOR",
"simplify_result": true
}Assistant: (Internal tool call) print_latex_tensor to display the Ricci tensor:
{
"tensor_key": "riccitensor_metric_AntiDeSitter"
}Result:
$$ \left[\begin{matrix}3 & 0 & 0 & 0\\0 & - 3 \cos^{2}{\left(t \right)} & 0 & 0\\0 & 0 & - 3 \cos^{2}{\left(t \right)} \sinh^{2}{\left(\chi \right)} & 0\\0 & 0 & 0 & - 3 \sin^{2}{\left(\theta \right)} \cos^{2}{\left(t \right)} \sinh^{2}{\left(\chi \right)}\end{matrix}\right] $$
Assistant: (Internal tool call) calculate_tensor to calculate the Ricci scalar:
{
"metric_key": "metric_AntiDeSitter",
"tensor_type": "RICCI_SCALAR",
"simplify_result": true
}Assistant: (Internal tool call) print_latex_tensor to display the Ricci scalar:
{
"tensor_key": "ricciscalar_metric_AntiDeSitter"
}Result:
$$ -12 $$
Example Interaction 3: Coupled ODE System (Fluid Dynamics)
This example demonstrates solving a coupled system of ODEs and verifying the solution against an algebraic steady-state analysis, a task where LLMs typically hallucinate without a CAS to ground each step.
User:
Use the sympy-mcp tools to solve this symbolically. Do not compute by hand.
Two cylindrical tanks are connected by a pipe. Tank 1 has cross-sectional area A₁ = 2 m² and receives a constant inflow of Q = 0.5 m³/s. Water drains from Tank 1 into Tank 2 through a pipe with flow rate proportional to the height difference: q₁₂ = k·(h₁ - h₂) where k = 0.3 m²/s. Tank 2 has cross-sectional area A₂ = 1 m² and drains to the outside at rate q₂ = k·h₂ with the same k.
Set up and solve the coupled system of ODEs for the water heights h₁(t) and h₂(t), starting from empty tanks (h₁(0) = 0, h₂(0) = 0). Then find the steady-state heights as t → ∞ by solving the equilibrium equations algebraically, and verify they match the long-term solution of the ODEs.
Assistant: (Internal tool chain)
intro_many: introducet,k,A1,A2,Qwith real/positive assumptionsintroduce_function× 2: introduceh1(t)andh2(t)as unknown functionsintroduce_expression× 2: encode the mass-balance ODEs:
$$A_1 \frac{dh_1}{dt} = Q - k(h_1 - h_2), \quad A_2 \frac{dh_2}{dt} = k(h_1 - h_2) - k h_2$$
substitute_expression: substitute numeric values fork,A1,A2,Qdsolve_ode× 2: solve the coupled system; apply initial conditions viasubstitute_expressionintroduce_expression× 2: encode equilibrium equations (derivatives set to zero)solve_linear_system: solve the 2×2 algebraic system forh1*,h2*print_latex_expression: display both the time-domain solution and the steady-state values
Security Disclaimer
This server runs on your computer and gives the language model access to run Python logic. Notably it uses Sympy's parse_expr to parse mathematical expressions, which is uses eval under the hood, effectively allowing arbitrary code execution. By running the server, you are trusting the code that Claude generates. Running in the Docker image is slightly safer, but it's still a good idea to review the code before running it.
parse_expr call sites
The following tools pass client-supplied strings to parse_expr with SymPy's default global
namespace (which includes Python builtins such as __import__, open, eval, exec):
introduce_expression(expr_str)integrate_expression(lower_bound,upper_bound)create_vector_field(component strings)create_matrix(string entries)convert_to_units(target unit strings)create_custom_metric(component strings)
For example introduce_expression("__import__('os').getpid()") executes the call. Passing
global_dict={} is not a mitigation: eval re-inserts the complete __builtins__ module into
an empty globals dictionary, and object attribute traversal (obj.__class__.__mro__...) remains
available regardless of the namespace. SymPy documents parse_expr/sympify as unsafe on untrusted
input. Resource exhaustion is also possible (e.g. 10**10**10), and no time limit is applied to any
tool. With the HTTP transports the server binds to 0.0.0.0 by default, which exposes these
risks to the network; prefer --mcp-host 127.0.0.1 or the stdio transport.
The algebra/calculus tools added in this fork (factor_expression, expand_expression,
cancel_expression, apart_expression, limit_expression, series_expansion,
solve_inequality) never call parse_expr, sympify or eval themselves; their only string
inputs are parsed by the allow-list parser described above. They still operate on expressions that
were created through introduce_expression, so they do not remove the risk of that entry point.
License
Copyright 2025 Stephen Diehl.
This project is licensed under the Apache 2.0 License. See the LICENSE file for details.
This server cannot be deployed
Maintenance
Related MCP Connectors
Math.js MCP — wraps the mathjs.org API (free, no auth)
Scientific compute for AI agents: symbolic, numerical, quantum, chemistry, ODE. Paid via x402.
This MCP server enables users to perform scientific computations regarding linear algebra and vect…
MCPCalc gives agents access to a comprehensive library of calculators spanning finance, math, health, construction, engineering, food, automotive, and more. It includes a full Computer Algebra System (CAS) and a grid-based Spreadsheet calculator.
Related MCP Servers
- AlicenseAqualityCmaintenanceA mathematical computation service that enables users to perform symbolic calculations including basic arithmetic, algebra, calculus, equation solving, and matrix operations through the MCP protocol.16MIT
- AlicenseCqualityCmaintenanceAn MCP server that provides access to SymPy's symbolic mathematics library for advanced algebraic computations. It enables users to perform complex tasks such as symbolic simplification, calculus, equation solving, matrix operations, and number theory.10041 PyPIMIT
- AlicenseAqualityDmaintenanceA symbolic mathematics MCP server supporting calculus, linear algebra, number theory, statistics, and unit conversion via natural language.8MIT
- AlicenseBqualityBmaintenanceMCP server for symbolic computation that enables AI agents to perform step-by-step derivations, transform formulas, and verify results with full provenance, combining natural language with formal mathematical operations.4171 PyPI12Apache 2.0