Skip to main content
Glama

sympy_mcp_equation_operation

Perform symbolic equation operations including solve, solveset, linsolve, and nonlinsolve for mathematical equations using SymPy integration within the Fermat MCP server.

Instructions

Do symbolic equation operations like solve, solveset, linsolve, nonlinsolve

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
operationYes
equationsYes
symbolsNo
domainNo
checkNo
simplifyNo
rationalNo
minimalNo
forceNo
implicitNo

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes

Implementation Reference

  • The handler function that executes the tool logic for various SymPy equation solving operations (solve, solveset, linsolve, nonlinsolve). Parses inputs, calls appropriate SymPy solvers, and formats output.
    def equation_operation(
        operation: EquationOperation,
        equations: Union[str, List[str]],
        symbols: Optional[Union[str, List[str]]] = None,
        # Common parameters
        domain: Optional[str] = None,
        # Additional parameters for specific solvers
        check: bool = True,
        simplify: bool = True,
        rational: Optional[bool] = None,
        minimal: bool = False,
        # Parameters for nonlinsolve
        force: bool = False,
        # Parameters for solveset
        implicit: bool = False,
    ) -> str:
        """
        Unified interface for equation solving operations.
    
        Args:
            operation: The equation operation to perform. One of:
                - 'solve': General purpose solver for algebraic equations
                - 'solveset': Solves equations with solution sets
                - 'linsolve': Solves system of linear equations
                - 'nonlinsolve': Solves system of nonlinear equations
            equations: The equation(s) to solve, as string(s) or SymPy expression(s)
            symbols: The variable(s) to solve for
            **kwargs: Additional arguments to pass to the underlying SymPy function:
                - For 'solve' and 'solveset':
                    - domain: The domain for solving (default: complex numbers)
                - For 'linsolve' and 'nonlinsolve':
                    - Additional arguments are passed to the respective solver
    
        Returns:
            str: The solution as a string in list format
    
        Examples:
            >>> equation_operation('solve', 'x**2 - 1', 'x')
            '[-1, 1]'
            >>> equation_operation('solveset', 'x**2 - 1', 'x')
            '{-1, 1}'
            >>> equation_operation('linsolve', ['x + y = 1', 'x - y = 0'], ['x', 'y'])
            '[(1/2, 1/2)]'
            >>> equation_operation('nonlinsolve', ['x**2 + y - 1', 'x - y'], ['x', 'y'])
            '[(-1/2 + sqrt(5)/2, -1/2 + sqrt(5)/2), (-sqrt(5)/2 - 1/2, -sqrt(5)/2 - 1/2)]'
        """
        # Parse input equations and symbols
        eqs = _parse_equations(equations)
        syms = _parse_symbols(symbols)
    
        # Handle different operations
        if operation == "solve":
            # General purpose solver
            if not syms:
                # Try to extract symbols automatically if not provided
                result = _solve(
                    eqs,
                    check=check,
                    simplify=simplify,
                    rational=rational,
                    minimal=minimal,
                    domain=domain,
                )
            else:
                result = _solve(
                    eqs,
                    syms,
                    check=check,
                    simplify=simplify,
                    rational=rational,
                    minimal=minimal,
                    domain=domain,
                )
    
        elif operation == "solveset":
            # Solver that returns solution sets
            if not eqs:
                raise ValueError("At least one equation must be provided")
            if not syms:
                raise ValueError("Symbols must be provided for solveset")
    
            if len(eqs) > 1 or len(syms) > 1:
                # Handle multiple equations or symbols
                result = []
                for eq in eqs:
                    for sym in syms:
                        result.append(
                            _solveset(
                                eq,
                                sym,
                                domain=domain,
                                check=check,
                                simplify=simplify,
                                implicit=implicit,
                            )
                        )
            else:
                result = _solveset(
                    eqs[0],
                    syms[0],
                    domain=domain,
                    check=check,
                    simplify=simplify,
                    implicit=implicit,
                )
    
        elif operation == "linsolve":
            # Linear system solver
            if not eqs:
                raise ValueError("At least one equation must be provided")
    
            # Convert to matrix form if needed
            if not syms:
                raise ValueError("Symbols must be provided for linsolve")
    
            # Convert to augmented matrix form if equations are in list form
            if all(isinstance(eq, Expr) for eq in eqs):
                # Equations are already in expression form
                result = _linsolve(eqs, *syms)
            else:
                # Try to convert string equations to matrix form
                A = []
                for eq in eqs:
                    if isinstance(eq, str):
                        if "=" in eq:
                            left, right = eq.split("=", 1)
                            A.append(sympify(left) - sympify(right))
                        else:
                            A.append(sympify(eq))
                    else:
                        A.append(eq)
                result = _linsolve(A, syms)
    
        elif operation == "nonlinsolve":
            # Nonlinear system solver
            if not eqs:
                raise ValueError("At least one equation must be provided")
            if not syms:
                raise ValueError("Symbols must be provided for nonlinsolve")
    
            result = _nonlinsolve(eqs, syms)
    
        else:
            valid_ops = get_args(EquationOperation)
            raise ValueError(f"Invalid operation. Must be one of: {valid_ops}")
    
        return _convert_to_set(result)
  • Registers the equation_operation function as a tool named sympy_mcp_equation_operation in the FastMCP server.
    sympy_mcp.tool(
        equation_operation,
        description="Do symbolic equation operations like solve, solveset, linsolve, nonlinsolve",
    )
  • Type definition for the 'operation' parameter, defining valid operations.
    EquationOperation = Literal["solve", "solveset", "linsolve", "nonlinsolve"]
  • Helper to parse input equations into SymPy Expr objects.
    def _parse_equations(equations: Union[str, List[str]]) -> List[Expr]:
        """Parse equations from various input formats."""
        if isinstance(equations, (str, Expr)):
            equations = [equations]
    
        parsed = []
        for eq in equations:
            if isinstance(eq, str):
                # Handle both 'x + y = 1' and 'Eq(x + y, 1)' formats
                if "=" in eq and not eq.strip().startswith("Eq("):
                    left, right = eq.split("=", 1)
                    parsed.append(Eq(sympify(left), sympify(right)))
                else:
                    parsed.append(sympify(eq))
            else:
                parsed.append(eq)
        return parsed
  • Helper to convert SymPy solution results to consistent string representation.
    def _convert_to_set(result) -> str:
        """Convert various SymPy solution formats to a consistent string representation."""
        if result is None:
            return "[]"
        elif isinstance(result, (list, tuple, set, frozenset, FiniteSet)):
            return str(list(result))
        elif isinstance(result, dict):
            return str([{str(k): str(v) for k, v in result.items()}])
        elif hasattr(result, "args") and hasattr(result, "free_symbols"):
            # Handle SymPy solution sets
            return str([str(result)])
        return str(result)
Behavior1/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. However, it only lists operation names without explaining what they do (e.g., solve for solutions, solveset for solution sets, linsolve for linear systems, nonlinsolve for nonlinear systems), their effects (e.g., returns symbolic expressions, may raise errors), or any constraints (e.g., performance, input formats). This leaves critical behavioral traits like output format, error handling, and computational limits completely unspecified.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is extremely concise, consisting of a single sentence that directly states the tool's purpose with no wasted words. It is front-loaded and efficiently communicates the core functionality, making it easy to scan. However, this conciseness comes at the cost of completeness, as noted in other dimensions.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the complexity (10 parameters, no annotations, 0% schema coverage) and the presence of an output schema, the description is incomplete. While the output schema may cover return values, the description lacks essential details: it doesn't explain the operations, parameter meanings, usage context, or behavioral traits. For a tool with many parameters and no annotation support, this minimal description is inadequate to guide effective use.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters1/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 10 parameters and 0% schema description coverage, the schema provides no descriptions for any parameters. The description adds no information about what parameters like 'equations', 'symbols', 'domain', or flags such as 'check' and 'simplify' mean, their expected formats, or how they interact with operations. This fails to compensate for the lack of schema documentation, leaving parameters largely unexplained.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states the tool performs symbolic equation operations and lists four specific operations (solve, solveset, linsolve, nonlinsolve), which provides a general purpose. However, it lacks specificity about what these operations do (e.g., solving equations vs. other symbolic manipulations) and doesn't clearly distinguish from sibling tools like sympy_mcp_algebra_operation or sympy_mcp_calculus_operation, which may have overlapping functionality. The phrase 'like solve, solveset, linsolve, nonlinsolve' is somewhat vague, as it doesn't define the scope beyond listing examples.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides no guidance on when to use this tool versus alternatives. It doesn't mention any context, prerequisites, or exclusions, such as when to choose this over sibling tools like sympy_mcp_algebra_operation or sympy_mcp_calculus_operation, or what types of equations are suitable. Without such information, users must infer usage from the operation names alone, which is insufficient for effective tool selection.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/abhiphile/fermat-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server