Skip to main content
Glama

solve_cvxpy_problem

Solve convex optimization problems defined with variables, objectives, and constraints using CVXPY. Returns solutions for mathematical programming tasks.

Instructions

Solve a CVXPY optimization problem.

This tool takes a CVXPY optimization problem defined with variables, objective,
and constraints, and returns a solution if one exists.

Example:

Solve the following problem:

    minimize ||Ax - b||₂²
    subject to:
    0 ≤ x ≤ 1
    where A = [1.0, -0.5; 0.5, 2.0; 0.0, 1.0] and b = [2.0, 1.0, -1.0]

Should be this tool call:

    simple_cvxpy_solver(
        variables=[{"name": "x", "shape": 2}],
        objective_type="minimize",
        objective_expr="cp.sum_squares(np.array(A) @ x - np.array(b))",
        constraints=["x >= 0", "x <= 1"],
        parameters={"A": [[1.0, -0.5], [0.5, 2.0], [0.0, 1.0]],
                    "b": [2.0, 1.0, -1.0]}
    )

Args:
    problem: The problem definition with variables, objective, and constraints

Returns:
    A list of TextContent containing the solution or an error message

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
problemYes

Implementation Reference

  • Core handler function that implements the CVXPY problem solving logic: creates variables, parses expressions for objective and constraints, solves the problem, extracts values and duals.
    def solve_cvxpy_problem(problem: CVXPYProblem) -> Result[CVXPYSolution, str]:
        """Solve a CVXPY optimization problem.
    
        Args:
            problem: The problem definition
    
        Returns:
            Result containing a CVXPYSolution or an error message
        """
        try:
            # Create variables
            variables: dict[str, cp.Variable] = {}
            for var in problem.variables:
                variables[var.name] = create_variable(var.name, var.shape)
    
            # Parse objective
            objective_expr = parse_expression(
                problem.objective.expression, variables, problem.parameters
            )
            objective = (
                cp.Minimize(objective_expr)
                if problem.objective.type == ObjectiveType.MINIMIZE
                else cp.Maximize(objective_expr)
            )
    
            # Parse constraints
            constraints = []
            for _i, constraint in enumerate(problem.constraints):
                constraint_expr = parse_expression(
                    constraint.expression, variables, problem.parameters
                )
                constraints.append(constraint_expr)
    
            # Create and solve the problem
            prob = cp.Problem(objective, constraints)
            result = prob.solve()
    
            # Extract solution
            values = {name: var.value for name, var in variables.items()}
            dual_values = {
                i: constraint.dual_value
                for i, constraint in enumerate(constraints)
                if hasattr(constraint, "dual_value") and constraint.dual_value is not None
            }
    
            return Success(
                CVXPYSolution(
                    values=values,
                    objective_value=float(result) if result is not None else None,
                    status=prob.status,
                    dual_values=dual_values if dual_values else None,
                )
            )
        except Exception as e:
            return Failure(f"Error solving CVXPY problem: {e!s}")
  • MCP tool handler registered with @app.tool('solve_cvxpy_problem'). Calls the core solve_cvxpy_problem function and formats the result as TextContent for MCP response.
    @app.tool("solve_cvxpy_problem")
    async def solve_cvxpy_problem_tool(problem: CVXPYProblem) -> list[TextContent]:
        """Solve a CVXPY optimization problem.
    
        This tool takes a CVXPY optimization problem defined with variables, objective,
        and constraints, and returns a solution if one exists.
    
        Example:
    
        Solve the following problem:
    
            minimize ||Ax - b||₂²
            subject to:
            0 ≤ x ≤ 1
            where A = [1.0, -0.5; 0.5, 2.0; 0.0, 1.0] and b = [2.0, 1.0, -1.0]
    
        Should be this tool call:
    
            simple_cvxpy_solver(
                variables=[{"name": "x", "shape": 2}],
                objective_type="minimize",
                objective_expr="cp.sum_squares(np.array(A) @ x - np.array(b))",
                constraints=["x >= 0", "x <= 1"],
                parameters={"A": [[1.0, -0.5], [0.5, 2.0], [0.0, 1.0]],
                            "b": [2.0, 1.0, -1.0]}
            )
    
        Args:
            problem: The problem definition with variables, objective, and constraints
    
        Returns:
            A list of TextContent containing the solution or an error message
        """
        result = solve_cvxpy_problem(problem)
    
        match result:
            case Success(solution):
                return [
                    TextContent(
                        type="text",
                        text=json.dumps(
                            {
                                "values": {
                                    k: v.tolist() if hasattr(v, "tolist") else v
                                    for k, v in solution.values.items()
                                },
                                "objective_value": solution.objective_value,
                                "status": solution.status,
                                "dual_values": {
                                    k: v.tolist() if hasattr(v, "tolist") else v
                                    for k, v in (solution.dual_values or {}).items()
                                },
                            }
                        ),
                    )
                ]
            case Failure(error):
                return [TextContent(type="text", text=f"Error solving problem: {error}")]
            case _:
                return [
                    TextContent(
                        type="text",
                        text="Unexpected error in solve_cvxpy_problem_tool",
                    )
                ]
  • Registration of the 'solve_cvxpy_problem' tool using FastMCP's @app.tool decorator.
    @app.tool("solve_cvxpy_problem")
  • Pydantic models defining the input schema (CVXPYProblem, CVXPYVariable, etc.) and output (CVXPYSolution) for the CVXPY solver.
    from enum import Enum
    from typing import Any
    
    from pydantic import BaseModel
    
    
    class ObjectiveType(str, Enum):
        """Enum for objective types in CVXPY."""
    
        MINIMIZE = "minimize"
        MAXIMIZE = "maximize"
    
    
    class CVXPYVariable(BaseModel):
        """Model representing a CVXPY variable."""
    
        name: str
        shape: int | tuple[int, ...]  # Can be scalar (int) or vector/matrix (tuple)
    
    
    class CVXPYConstraint(BaseModel):
        """Model representing a CVXPY constraint."""
    
        expression: str  # String representation of the constraint
        description: str = ""
    
    
    class CVXPYObjective(BaseModel):
        """Model representing a CVXPY objective."""
    
        type: ObjectiveType
        expression: str  # String representation of the objective function
    
    
    class CVXPYProblem(BaseModel):
        """Model representing a complete CVXPY optimization problem."""
    
        variables: list[CVXPYVariable]
        objective: CVXPYObjective
        constraints: list[CVXPYConstraint]
        parameters: dict[str, Any] = {}  # For A, b, etc.
        description: str = ""
    
    
    class CVXPYSolution(BaseModel):
        """Model representing a solution to a CVXPY problem."""
    
        values: dict[str, Any]  # Variable values
        objective_value: float | None
        status: str
        dual_values: dict[int, Any] | None = None  # Constraint index to dual value
  • Helper function to parse string expressions into CVXPY expressions using safe eval with variables and parameters.
    def parse_expression(
        expr_str: str, variables: dict[str, cp.Variable], params: dict[str, Any]
    ) -> CVXPYExpr:
        """Parse a CVXPY expression string.
    
        Args:
            expr_str: String representation of the expression
            variables: Dictionary of variable names to CVXPY variables
            params: Dictionary of parameter names to values
    
        Returns:
            Parsed CVXPY expression
        """
        # Create a local dictionary with variables and parameters
        local_dict = {
            **variables,
            **params,
            "cp": cp,
            "np": np,
        }
    
        # Evaluate the expression in the context of the local dictionary
        return eval(expr_str, {"__builtins__": {}}, local_dict)
Behavior3/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It states the tool 'returns a solution if one exists' and mentions 'an error message' in the Returns section, which provides basic outcome information. However, it lacks details on performance characteristics, computational limits, solver configurations, or what happens with infeasible/unbounded problems. The description adds some value but leaves significant behavioral aspects unspecified.

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

Conciseness4/5

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

The description is well-structured with a clear purpose statement, example, and parameter/return sections. The example is detailed but necessary for understanding the complex parameter structure. Some sentences could be more concise (e.g., the Returns section is somewhat redundant), but overall the information is efficiently presented.

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

Completeness3/5

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

Given the complexity of optimization solving (no annotations, no output schema, 1 complex parameter with nested objects), the description provides a good foundation but has gaps. The example helps understand parameter structure, but there's no information about return format beyond 'list of TextContent', no error handling details, and no guidance on solver limitations. For a tool with this complexity, more complete documentation would be beneficial.

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

Parameters4/5

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

The input schema has 0% description coverage (no parameter descriptions in schema), so the description must compensate. It provides a detailed example showing how to structure the 'problem' parameter with variables, objective, constraints, and parameters. This adds substantial semantic value beyond the bare schema structure. However, it doesn't explain all possible parameter configurations or edge cases.

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's purpose: 'Solve a CVXPY optimization problem defined with variables, objective, and constraints, and returns a solution if one exists.' This specifies the verb ('solve'), resource ('CVXPY optimization problem'), and outcome. However, it doesn't explicitly differentiate from sibling tools like 'simple_cvxpy_solver' or 'solve_ortools_problem', which appear to be similar optimization solvers.

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 its siblings. With multiple solver tools available (e.g., simple_cvxpy_solver, solve_ortools_problem, solve_z3), there's no indication of which solver is appropriate for which types of problems, performance characteristics, or compatibility differences. The example shows usage but doesn't provide comparative context.

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/sdiehl/usolver'

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