Skip to main content
Glama
Sharmarajnish

Constrained Optimization MCP Server

solve_constraint_programming

Solve combinatorial optimization problems with logical and numerical constraints using OR-Tools for scheduling, assignment, and constraint satisfaction.

Instructions

Solve constraint programming problems using OR-Tools. This tool is ideal for combinatorial optimization problems, scheduling, assignment problems, and constraint satisfaction with discrete variables. Args: variables: List of variable definitions with 'name', 'type', and optional 'domain'/'shape' constraints: List of constraint expressions as strings objective: Optional objective definition with 'type' and 'expression' parameters: Dictionary of solver parameters description: Optional problem description Returns: Solution results including variable values and feasibility status Example: variables = [ {"name": "x", "type": "integer", "domain": [0, 10]}, {"name": "y", "type": "boolean"} ] constraints = [ "x + y >= 5", "x - y <= 3" ] objective = {"type": "minimize", "expression": "x + y"}

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
constraintsYes
descriptionNo
objectiveNo
parametersNo
variablesYes

Implementation Reference

  • MCP tool handler: validates inputs, constructs ORToolsProblem from dicts, calls solve_ortools_problem, serializes result to JSON text.
    @app.tool("solve_constraint_programming") async def solve_constraint_programming( variables: List[dict[str, Any]], constraints: List[str], objective: dict[str, Any] = None, parameters: dict[str, Any] = None, description: str = "", ) -> List[TextContent]: """ Solve constraint programming problems using OR-Tools. This tool is ideal for combinatorial optimization problems, scheduling, assignment problems, and constraint satisfaction with discrete variables. Args: variables: List of variable definitions with 'name', 'type', and optional 'domain'/'shape' constraints: List of constraint expressions as strings objective: Optional objective definition with 'type' and 'expression' parameters: Dictionary of solver parameters description: Optional problem description Returns: Solution results including variable values and feasibility status Example: variables = [ {"name": "x", "type": "integer", "domain": [0, 10]}, {"name": "y", "type": "boolean"} ] constraints = [ "x + y >= 5", "x - y <= 3" ] objective = {"type": "minimize", "expression": "x + y"} """ try: # Convert to OR-Tools problem problem_variables = [] for var in variables: if "name" not in var or "type" not in var: return [ TextContent( type="text", text="Each variable must have 'name' and 'type' fields", ) ] try: from ..models.ortools_models import ORToolsVariableType var_type = ORToolsVariableType(var["type"]) except ValueError: return [ TextContent( type="text", text=( f"Invalid variable type: {var['type']}. " f"Must be one of: boolean, integer, interval" ), ) ] problem_variables.append(ORToolsVariable(**var)) problem_constraints = [ORToolsConstraint(expression=expr) for expr in constraints] # Create objective if provided problem_objective = None if objective: try: from ..models.ortools_models import ORToolsObjectiveType obj_type = ORToolsObjectiveType(objective["type"]) problem_objective = ORToolsObjective( type=obj_type, expression=objective.get("expression"), description=objective.get("description", "") ) except ValueError: return [ TextContent( type="text", text=( f"Invalid objective type: {objective['type']}. " f"Must be one of: minimize, maximize, feasibility" ), ) ] problem = ORToolsProblem( variables=problem_variables, constraints=problem_constraints, objective=problem_objective, parameters=parameters or {}, description=description, ) # Solve the problem result = solve_ortools_problem(problem) match result: case Success(solution): return [ TextContent( type="text", text=json.dumps( { "values": solution.values, "is_feasible": solution.is_feasible, "status": solution.status, "objective_value": solution.objective_value, "solve_time": solution.solve_time, "statistics": solution.statistics, } ), ) ] case Failure(error): return [TextContent(type="text", text=f"Error solving problem: {error}")] except Exception as e: return [TextContent(type="text", text=f"Error in solve_constraint_programming: {e!s}")]
  • FastMCP tool registration decorator binding the handler function to the tool name 'solve_constraint_programming'.
    @app.tool("solve_constraint_programming")
  • Core solver implementation using OR-Tools CP-SAT: builds CpModel, creates variables/constraints/objective, solves, extracts solution and statistics.
    def solve_ortools_problem(problem: ORToolsProblem) -> Result[ORToolsSolution, str]: """Solve an OR-Tools problem and return the solution. Args: problem: The problem definition Returns: Result containing a Solution or an error message """ try: # Validate problem if not problem.validate(): return Failure("Invalid problem definition") start_time = time.time() # Create model model = cp_model.CpModel() # Create variables vars_result = create_variables(model, problem.variables) if isinstance(vars_result, Failure): return vars_result variables_dict, globals_dict = vars_result.unwrap() # Create constraints constraints_result = create_constraints( model, problem.constraints, variables_dict, globals_dict ) if isinstance(constraints_result, Failure): return constraints_result # Add objective objective_result = add_objective( model, problem.objective, variables_dict, globals_dict ) if isinstance(objective_result, Failure): return objective_result # Create solver solver = cp_model.CpSolver() # Add parameters if provided if problem.parameters: for key, value in problem.parameters.items(): if hasattr(solver.parameters, key): setattr(solver.parameters, key, value) # Set time limit if specified if problem.time_limit: solver.parameters.max_time_in_seconds = problem.time_limit # Solve the problem status = solver.Solve(model) solve_time = time.time() - start_time # Extract solution is_feasible = status in [ cp_model.OPTIMAL, cp_model.FEASIBLE, ] values = ( extract_solution(solver, variables_dict, problem.variables) if is_feasible else {} ) # Create solver statistics statistics = { "num_conflicts": solver.NumConflicts(), "num_branches": solver.NumBranches(), "wall_time": solver.WallTime(), "solve_time": solve_time, } return Success( ORToolsSolution( values=values, is_feasible=is_feasible, status=solver.StatusName(status), objective_value=( solver.ObjectiveValue() if is_feasible and problem.objective else None ), solve_time=solve_time, statistics=statistics, ) ) except Exception as e: return Failure(f"Error solving problem: {e!s}")
  • Pydantic model defining input schema for OR-Tools problems, used by the handler and solver for validation and type safety.
    class ORToolsProblem(BaseProblem): """Model representing a complete OR-Tools constraint programming problem.""" variables: List[ORToolsVariable] = Field(..., description="Problem variables") constraints: List[ORToolsConstraint] = Field(..., description="Problem constraints") objective: Optional[ORToolsObjective] = Field(default=None, description="Problem objective") parameters: Dict[str, Any] = Field(default_factory=dict, description="Problem parameters") description: str = Field(default="", description="Problem description") # Base problem properties problem_type: ProblemType = Field(default=ProblemType.CONSTRAINT_PROGRAMMING, description="Problem type") sense: OptimizationSense = Field(..., description="Optimization sense") # OR-Tools specific properties solver_type: str = Field(default="cp", description="Solver type (cp, sat, etc.)") time_limit: Optional[float] = Field(default=None, description="Time limit in seconds") search_strategy: Optional[str] = Field(default=None, description="Search strategy") log_search_progress: bool = Field(default=False, description="Log search progress") def get_variables(self) -> List[BaseVariable]: """Get all variables in the problem.""" return self.variables def get_constraints(self) -> List[BaseConstraint]: """Get all constraints in the problem.""" return self.constraints def validate(self) -> bool: """Validate the problem definition.""" if not self.variables: return False # Check that all variable names are unique var_names = [var.name for var in self.variables] if len(var_names) != len(set(var_names)): return False return True

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/Sharmarajnish/MCP-Constrained-Optimization'

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