Skip to main content
Glama

sympy_mcp_matrix_operation

Perform symbolic matrix operations including creation, determinant calculation, inversion, row reduction, and eigenvalue computation using SymPy integration.

Instructions

Do symbolic matrix operations like create, det, inv, rref, eigenvals

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
operationYes
dataYes
rationalNo
nrowsNo
ncolsNo
simplifyNo

Implementation Reference

  • Core handler function implementing the sympy_mcp_matrix_operation tool. Parses input matrix data, performs the specified SymPy matrix operation (det, inv, rref, eigenvals, create), and returns a serializable result.
    def matrix_operation(
        operation: MatrixOperation,
        data: Union[str, List, Tuple],
        # Create parameters
        rational: bool = True,
        nrows: Optional[int] = None,
        ncols: Optional[int] = None,
        # Common parameters
        simplify: bool = True,
    ) -> Any:
        """
        Unified interface for matrix operations.
    
        Args:
            operation: The matrix operation to perform. One of:
                - 'create': Create a matrix from data
                - 'det': Calculate the determinant
                - 'inv': Calculate the inverse
                - 'rref': Compute reduced row echelon form
                - 'eigenvals': Compute eigenvalues
            data: The matrix data in one of these formats:
                - String: "1 2; 3 4" or "[1, 2] [3, 4]"
                - List of lists: [[1, 2], [3, 4]]
                - Single list: [1, 2, 3, 4] (will be converted to a row matrix)
            rational: If True, convert to rational numbers (default: True)
            nrows, ncols: For creating matrices of specific dimensions
            simplify: If True, simplify the result (default: True)
    
        Returns:
            The result of the operation in a JSON-serializable format.
            For 'create', returns the matrix as a list of lists.
            For 'det', returns the determinant as a float or symbolic expression.
            For 'inv', returns the inverse matrix as a list of lists.
            For 'rref', returns a tuple (RREF_matrix, pivot_columns).
            For 'eigenvals', returns a dictionary of eigenvalues with multiplicities.
    
        Examples:
            >>> matrix_operation('create', '1 2; 3 4')
            [[1, 2], [3, 4]]
            >>> matrix_operation('det', [[1, 2], [3, 4]])
            -2
            >>> matrix_operation('inv', '1 2; 3 4')
            [[-2.0, 1.0], [1.5, -0.5]]
            >>> matrix_operation('rref', '1 2 3; 4 5 6')
            ([[1, 0, -1], [0, 1, 2]], (0, 1))
            >>> matrix_operation('eigenvals', '3 -2; 4 -1')
            {'1 - 2*I': 1, '1 + 2*I': 1}
        """
        # Parse matrix data
        matrix_data = _parse_matrix_data(data)
    
        # Create matrix, optionally converting to rational numbers
        if rational:
            matrix = Matrix(matrix_data).applyfunc(lambda x: nsimplify(x, rational=True))
        else:
            matrix = Matrix(matrix_data)
    
        # Handle matrix reshaping if nrows/ncols are provided
        if nrows is not None and ncols is not None:
            matrix = matrix.reshape(nrows, ncols)
        elif nrows is not None:
            matrix = matrix.reshape(nrows, -1)
        elif ncols is not None:
            matrix = matrix.reshape(-1, ncols)
    
        # Handle different operations
        if operation == "create":
            return _convert_to_json_serializable(matrix.tolist())
    
        # For other operations, ensure the matrix is square if needed
        if operation in ["det", "inv", "eigenvals"] and matrix.rows != matrix.cols:
            raise ValueError(f"Matrix must be square for {operation} operation")
    
        if operation == "det":
            try:
                det = matrix.det()
                return float(det) if det.is_real else str(det)
            except (TypeError, AttributeError):
                return str(det)
    
        elif operation == "inv":
            try:
                inv_matrix = matrix.inv()
                return _convert_to_json_serializable(inv_matrix.tolist())
            except ValueError as e:
                if "matrix is not invertible" in str(e).lower():
                    raise ValueError("Matrix is not invertible (determinant is zero)")
                raise
    
        elif operation == "rref":
            rref_matrix, pivot_columns = matrix.rref()
            return (
                _convert_to_json_serializable(rref_matrix.tolist()),
                tuple(pivot_columns),
            )
    
        elif operation == "eigenvals":
            try:
                eigenvals = matrix.eigenvals()
                # Convert to a serializable format with better handling of complex numbers
                result = {}
                for val, mult in eigenvals.items():
                    # Convert to complex and format nicely
                    cval = complex(val.evalf())
                    if abs(cval.imag) < 1e-10:  # Effectively real
                        key = f"{cval.real:.6f}".rstrip("0").rstrip(".")
                    else:  # Complex number
                        real_part = f"{cval.real:.6f}".rstrip("0").rstrip(".")
                        imag_part = f"{abs(cval.imag):.6f}".rstrip("0").rstrip(".")
                        sign = " + " if cval.imag >= 0 else " - "
                        key = f"{real_part}{sign}{imag_part}j"
                    result[key] = int(mult)
                return result
            except Exception as e:
                raise ValueError(f"Failed to compute eigenvalues: {str(e)}")
    
        else:
            valid_ops = get_args(MatrixOperation)
            raise ValueError(f"Invalid operation. Must be one of: {valid_ops}")
  • Registers the matrix_operation handler as the 'sympy_mcp_matrix_operation' tool in the FastMCP sympy_mcp server.
    sympy_mcp.tool(
        matrix_operation,
        description="Do symbolic matrix operations like create, det, inv, rref, eigenvals",
    )
  • Type definition for the 'operation' parameter schema, listing valid matrix operations.
    MatrixOperation = Literal["create", "det", "inv", "rref", "eigenvals"]
  • Helper function to parse flexible matrix input data into SymPy-compatible format.
    def _parse_matrix_data(data: Union[List, Tuple, str]) -> List[List[Any]]:
        """Parse matrix data from various input formats."""
        if isinstance(data, str):
            # Handle string input like "1 2; 3 4" or "[1, 2] [3, 4]"
            if ";" in data:
                # Handle MATLAB-style format: "1 2; 3 4"
                rows = [row.strip() for row in data.split(";") if row.strip()]
                return [[sympify(x) for x in row.split()] for row in rows]
            else:
                # Handle list of lists format: "[1, 2] [3, 4]"
                import ast
    
                try:
                    # Try to parse as a list of lists
                    parsed = ast.literal_eval("[" + data.replace(" ", ",") + "]")
                    if all(isinstance(row, (list, tuple)) for row in parsed):
                        return [[sympify(x) for x in row] for row in parsed]
                    elif all(not isinstance(x, (list, tuple)) for x in parsed):
                        # Single row matrix
                        return [[sympify(x) for x in parsed]]
                except (ValueError, SyntaxError):
                    pass
    
                # Try space-separated values
                return [
                    [sympify(x) for x in row.split()]
                    for row in data.split("\n")
                    if row.strip()
                ]
    
        # Handle list/tuple input
        if all(isinstance(row, (list, tuple)) for row in data):
            return [[sympify(x) for x in row] for row in data]
        elif all(not isinstance(x, (list, tuple)) for x in data):
            # Single row matrix
            return [[sympify(x) for x in data]]
    
        raise ValueError("Invalid matrix format")
  • Helper function to serialize SymPy results for JSON output.
    def _convert_to_json_serializable(obj):
        """Convert SymPy objects to JSON-serializable types."""
        if hasattr(obj, "as_immutable"):
            return str(obj)
        elif isinstance(obj, (list, tuple)):
            return [_convert_to_json_serializable(x) for x in obj]
        elif isinstance(obj, dict):
            return {str(k): _convert_to_json_serializable(v) for k, v in obj.items()}
        return obj
Behavior2/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. It mentions 'symbolic matrix operations' which implies mathematical computation, but doesn't disclose behavioral traits like error handling, performance characteristics, whether operations are read-only or mutating, or what the output format looks like. The description is too minimal for a tool with 6 parameters.

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 with a single sentence that efficiently lists the key operations. It's front-loaded with the core purpose and wastes no words, though this conciseness comes at the cost of completeness.

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?

For a tool with 6 parameters, 0% schema description coverage, no annotations, and no output schema, the description is inadequate. It doesn't explain parameter usage, return values, error conditions, or behavioral expectations. The minimal description fails to provide necessary context for proper tool invocation.

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

Parameters2/5

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

Schema description coverage is 0%, so the description must compensate. It lists operation types but doesn't explain what 'data' parameter should contain, what 'rational' and 'simplify' flags do, or when 'nrows' and 'ncols' are needed. The description adds minimal value beyond the schema's enum for 'operation'.

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

Purpose4/5

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

The description clearly states the tool performs symbolic matrix operations and lists specific operations (create, det, inv, rref, eigenvals), providing a specific verb+resource combination. However, it doesn't explicitly differentiate from sibling tools like sympy_mcp_algebra_operation or numpy_mcp_matlib_operation, which might also handle matrix operations.

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 like sympy_mcp_algebra_operation or numpy_mcp_matlib_operation. It lists operations but doesn't specify context, prerequisites, or exclusions for usage.

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