CHUK MCP Solver
Click on "Install 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., "@CHUK MCP Solverschedule 5 tasks with dependencies to finish as soon as possible"
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.
CHUK MCP Solver
🔧 General-purpose constraint and optimization solver as an MCP server
A powerful Model Context Protocol (MCP) server that provides constraint satisfaction and optimization capabilities to LLMs and AI agents. Built on Google OR-Tools CP-SAT solver, it enables sophisticated decision-making for scheduling, resource allocation, puzzles, and more.
Features
✨ General Constraint Solver
Integer and boolean variables
Linear constraints
Global constraints (all_different, element, table)
Implication constraints (conditional logic)
Scheduling constraints (cumulative, no_overlap)
Routing constraints (circuit)
Inventory constraints (reservoir)
Satisfaction and optimization modes
🎯 Wide Range of Use Cases
Project scheduling and resource allocation
Logic puzzles (Sudoku, etc.)
Knapsack and packing problems
Tool/model selection under constraints
Configuration optimization
Budget allocation
🚀 Quality Assured
Async/await native
Type-safe with Pydantic models
Comprehensive test coverage (95%)
Clean architecture with provider pattern
Configurable via environment or YAML
📊 Rich Solutions
Optimal and feasible solutions
Multi-objective optimization (priority-based)
Warm-start from previous solutions
Parallel search workers
Binding constraint analysis
Human-readable explanations
Metadata preservation
🤖 LLM-Optimized (Phase 2: Developer Experience)
Pre-solve validation with actionable error messages
Smart typo detection ("Did you mean...?" suggestions)
Three-level validation severity (ERROR, WARNING, INFO)
Structured observability and diagnostics
Detailed infeasibility analysis
⚡ Performance & Power (Phase 3)
Solution caching with problem hashing (LRU + TTL)
Partial solutions (best-so-far on timeout)
Search strategy hints (first-fail, random, etc.)
Deterministic solving with random seeds
Cache hit rate tracking
✅ Production Quality
246 comprehensive tests (all passing)
94% test coverage
Type-safe with mypy
Extensive error handling
🎯 High-Level Problem APIs (Phase 4: LLM-Native Schemas) 🆕
Scheduling: Tasks with dependencies, resources, deadlines → optimal project schedules
Routing: TSP/VRP with locations and vehicles → optimal delivery routes
✨ Multi-vehicle VRP with capacity constraints (Phase 1 - NEW!)
Single-vehicle TSP, minimize distance/time/cost/vehicles objectives
Load timeline tracking, service times, vehicle-specific costs
Budget Allocation: Items with costs, values, dependencies → optimal portfolio selection
Assignment: Tasks with skills to agents with capacity → optimal task-agent matching
Automatically builds CP-SAT models from high-level specs
Domain-specific validation and error messages
Rich responses with critical paths, utilization, route sequences, resource usage, assignments
Related MCP server: Constrained Optimization MCP Server
Example Use Cases
High-Level Problem APIs (🆕 Phase 4)
📅 Project Manager: "Schedule 15 tasks with dependencies and resource constraints to finish ASAP"
High-level API:
solve_scheduling_problem(tasks, resources, objective="minimize_makespan")No need to understand CP-SAT variables or cumulative constraints
Returns: optimal schedule with start/end times, critical path, resource utilization
See:
scheduling_demo.py
🚚 Delivery Driver: "Find the shortest route visiting 10 customers with 2 trucks, respecting vehicle capacity"
High-level API:
solve_routing_problem(locations, vehicles, objective="minimize_distance")✨ Now supports multi-vehicle VRP with capacity constraints!
No need to understand flow conservation, MTZ constraints, or subtour elimination
Returns: optimal routes per vehicle, total distance, load timelines
See:
routing_demo.pyandvrp_multi_vehicle_demo.py
💰 Product Manager: "Select projects to maximize ROI under $100k budget with dependencies and conflicts"
High-level API:
solve_budget_allocation(items, budgets, objective="maximize_value")No need to understand knapsack patterns or implication constraints
Returns: selected items, total cost/value, resource usage, slack analysis
See:
allocation_demo.py
👥 Team Lead: "Assign development tasks to engineers matching required skills and balancing workload"
High-level API:
solve_assignment_problem(agents, tasks, objective="balance_load")No need to understand binary assignment variables or capacity constraints
Returns: optimal assignments, agent workload, over/underutilized agents
See:
assignment_demo.py
Low-Level Constraint Programming
🏗️ DevOps Team: "Schedule 20 deployment tasks across 5 servers with CPU/memory limits while minimizing total deployment time"
Uses cumulative constraints to manage resource capacity
Optimizes makespan while respecting dependencies
🚚 Logistics Company: "Plan delivery routes for 10 trucks visiting 50 customers to minimize total distance"
Uses circuit constraints for vehicle routing (TSP/VRP)
Handles time windows and capacity constraints
See:
delivery_router.py
📦 Warehouse Manager: "Schedule production runs and customer orders while maintaining safety stock of 500 units"
Uses reservoir constraints to track inventory levels
Prevents stockouts and overstock situations
See:
inventory_manager.py
☁️ Cloud Architect: "Select AWS instances to meet requirements while minimizing cost, then latency"
Uses multi-objective optimization with priorities
Balances competing objectives (cost vs performance)
🤖 AI Platform: "Route 100 user requests to GPT-4, GPT-3.5, or Claude to minimize cost under $50 budget"
Uses implication constraints for conditional logic
Selects optimal model for each task based on capabilities
See:
tool_selector.py
🎯 Project Manager: "Schedule 10 tasks with dependencies to minimize project completion time"
Uses linear constraints for precedence relationships
Optimizes critical path and resource allocation
See:
project_scheduler.py
🧩 Puzzle Solver: "Solve a Sudoku puzzle or find valid N-Queens placement"
Uses all_different constraints for logic puzzles
Demonstrates pure constraint satisfaction
See:
sudoku_solver.py
💼 Budget Planner: "Allocate $10,000 across 20 initiatives to maximize ROI under capacity constraints"
Uses knapsack optimization for resource allocation
Handles multiple constraints (budget, headcount, time)
LLM/AI Agent Examples
"Claude, I need to schedule a team meeting with 5 people. Alice is only free Mon/Wed, Bob can't do mornings, and Carol must attend before David. Find a time that works."
LLM extracts: 5 people, availability constraints, precedence constraint
Solver finds: Valid meeting time satisfying all constraints
Response: "Schedule meeting Wednesday 2-3pm: Alice, Bob, Carol attend first half; David joins after Carol confirms"
"Help me plan a road trip visiting San Francisco, LA, Vegas, and Phoenix in the shortest route starting from Seattle."
LLM converts to: TSP problem with 5 cities
Solver optimizes: Circuit constraint for minimum distance route
Response: "Optimal route (1,247 miles): Seattle → SF (808mi) → LA (382mi) → Vegas (270mi) → Phoenix (297mi) → Seattle (1,440mi)"
"I have $500/month for AI API costs. I need to process 10,000 text requests and 2,000 image requests. What's the cheapest mix of GPT-4, GPT-3.5, and Claude?"
LLM builds: Cost optimization problem with budget constraint
Solver finds: Optimal model selection minimizing cost
Response: "Use GPT-3.5 for 8,000 text ($40), Claude for 2,000 text ($30), GPT-4 for 2,000 images ($400). Total: $470/month"
"I'm deploying a microservice that needs 16 CPU cores and 32GB RAM. Minimize cost but keep latency under 50ms. What AWS instances should I use?"
LLM creates: Multi-objective problem (cost priority 1, latency priority 2)
Solver optimizes: Instance selection meeting requirements
Response: "Deploy 4x c5.large instances (16 cores, 32GB total) at $340/month with 30ms latency"
"We have 3 devs, 2 designers, 1 PM. Schedule 15 tasks over 2 weeks where: Task A needs 2 devs for 3 days, Task B needs 1 designer + 1 dev for 2 days, all tasks have dependencies."
LLM extracts: Resource requirements, durations, dependencies
Solver schedules: Cumulative resource constraints + precedence
Response: "Project completes in 12 days. Task A: Days 1-3 (Alice, Bob). Task B: Days 4-5 (Carol, David)..."
"I need to maintain 500 units of inventory. I have supplier deliveries on days 1, 7, 14 and customer orders on days 3, 5, 10, 15. When should I schedule each delivery to never run out?"
LLM models: Reservoir constraint problem with stock levels
Solver finds: Valid delivery schedule maintaining safety stock
Response: "Schedule delivery 1 on day 0 (300 units), delivery 2 on day 6 (250 units), delivery 3 on day 12 (200 units). Stock never drops below 500."
"Find me a valid Sudoku solution for this puzzle..."
LLM recognizes: Constraint satisfaction problem
Solver finds: Valid solution using all_different constraints
Response: Shows completed Sudoku grid
"I have 10 research papers to review. Each needs 2-4 hours. Some must be done before others. I have 20 hours this week. Create an optimal schedule."
LLM extracts: Tasks, durations, precedence, time budget
Solver optimizes: Maximize papers reviewed in 20 hours
Response: "Can complete 7 papers in 20 hours: Paper A (2h, Mon 9-11am), Paper D (3h, Mon 11am-2pm)..."
Installation
⚡ Quick Start with uvx (Recommended)
No installation required! Use uvx to run directly:
# Run directly without installation
uvx chuk-mcp-solverOr install with uvx:
# Install globally
uvx install chuk-mcp-solver🌐 Public MCP Endpoint
Use our hosted solver directly - no installation needed:
MCP Endpoint:
https://solver.chukai.io/mcp
Perfect for testing, demos, or production use without infrastructure setup.
Install from PyPI
# With pip
pip install chuk-mcp-solver
# With uv (faster)
uv pip install chuk-mcp-solverLocal Development
# Navigate to project and install
cd chuk-mcp-solver
uv pip install -e ".[dev]"Quick Start
As an MCP Server
Option 1: Public Hosted Endpoint (Easiest)
Use our hosted solver at solver.chukai.io - no installation required!
Add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):
{
"mcpServers": {
"solver": {
"url": "https://solver.chukai.io/mcp"
}
}
}Option 2: Local with uvx (Recommended)
Run locally using uvx for full control and privacy:
{
"mcpServers": {
"solver": {
"command": "uvx",
"args": ["chuk-mcp-solver"]
}
}
}Option 3: Development Mode
For local development from source:
{
"mcpServers": {
"solver": {
"command": "uv",
"args": ["run", "chuk-mcp-solver"],
"cwd": "/path/to/chuk-mcp-solver"
}
}
}With Docker
Build and run using Docker:
# Build the image
docker build -t chuk-mcp-solver .
# Run the container
docker run -p 8000:8000 chuk-mcp-solver
# Or use docker-compose
docker-compose up -dThe Docker container runs the MCP server in HTTP mode by default on port 8000. For stdio mode (local usage), run without arguments: python -m chuk_mcp_solver.server
Programmatic Usage
from chuk_mcp_solver.models import SolveConstraintModelRequest
from chuk_mcp_solver.solver import get_solver
# Define a simple optimization problem
request = SolveConstraintModelRequest(
mode="optimize",
variables=[
{"id": "x", "domain": {"type": "integer", "lower": 0, "upper": 10}},
{"id": "y", "domain": {"type": "integer", "lower": 0, "upper": 10}},
],
constraints=[
{
"id": "capacity",
"kind": "linear",
"params": {
"terms": [{"var": "x", "coef": 2}, {"var": "y", "coef": 3}],
"sense": "<=",
"rhs": 15,
},
}
],
objective={
"sense": "max",
"terms": [{"var": "x", "coef": 5}, {"var": "y", "coef": 4}],
},
)
# Solve
solver = get_solver("ortools")
response = await solver.solve_constraint_model(request)
print(f"Status: {response.status}")
print(f"Objective: {response.objective_value}")
for var in response.solutions[0].variables:
print(f" {var.id} = {var.value}")Examples
The examples/ directory contains 16 complete examples demonstrating different constraint types and use cases:
High-Level Problem APIs
Scheduling Demo (scheduling_demo.py) 🆕
API:
solve_scheduling_problem- High-level scheduling interfaceUse Case: Project scheduling, resource allocation, DevOps pipelines
Features: Tasks with dependencies, resource constraints, deadlines, release times
python examples/scheduling_demo.pyShows 6 scheduling scenarios:
Simple sequential project (build → test → deploy)
Parallel task execution
Resource-constrained scheduling with capacity limits
Deadlines and earliest start times
Infeasible problem detection
Complex DevOps pipeline with mixed constraints
Routing Demo (routing_demo.py) 🆕
API:
solve_routing_problem- High-level TSP/VRP interfaceUse Case: Delivery routing, traveling salesman, logistics optimization
Features: Coordinates or distance matrix, service times, vehicle costs
python examples/routing_demo.pyShows 6 routing scenarios:
Simple TSP with coordinates
TSP with asymmetric distance matrix
TSP with service times at locations
TSP with cost optimization (fixed + variable)
Real-world 7-location delivery route
Small 3-city TSP with detailed breakdown
Budget Allocation Demo (allocation_demo.py) 🆕
API:
solve_budget_allocation- High-level knapsack/portfolio interfaceUse Case: Project selection, feature prioritization, resource allocation
Features: Dependencies, conflicts, multi-resource constraints, min/max thresholds
python examples/allocation_demo.pyShows 7 allocation scenarios:
Simple knapsack problem (maximize value under budget)
Portfolio selection with dependencies (backend required for frontend)
Feature prioritization with conflicts (mobile vs web checkout)
Multi-resource allocation (budget + headcount + time)
Maximize item count (get as many as possible)
Minimize cost while meeting value threshold
Item count constraints (min/max selection limits)
Assignment Demo (assignment_demo.py) 🆕
API:
solve_assignment_problem- High-level task-agent assignment interfaceUse Case: Work assignment, task delegation, resource matching
Features: Skill matching, capacity constraints, load balancing, cost optimization
python examples/assignment_demo.pyShows 7 assignment scenarios:
Simple assignment (minimize cost with different hourly rates)
Skill matching (assign tasks requiring specific skills to qualified agents)
Load balancing (distribute tasks evenly across agents)
Capacity constraints (agents with limited task capacity)
Maximize assignments (assign as many tasks as possible)
Infeasible assignment (insufficient capacity)
Custom cost matrix (task-agent preference matching)
Performance & Features
Performance Metrics Demo (performance_metrics_demo.py) 🆕
Features: Enhanced status codes, optimality gap, solve timing
Use Case: Understanding solver performance and timeout behavior
python examples/performance_metrics_demo.pyDemonstrates the new v0.2.0+ performance metrics: optimality_gap, solve_time_ms, timeout_best, and timeout_no_solution status codes.
Logic & Constraint Satisfaction
Sudoku Solver (sudoku_solver.py)
Constraints: all_different
Use Case: Logic puzzles, constraint satisfaction
python examples/sudoku_solver.pySolves a 4x4 Sudoku puzzle using all_different constraints for rows, columns, and boxes.
Optimization Problems
Knapsack Optimizer (knapsack_optimizer.py)
Constraints: Linear (capacity), binary variables
Use Case: Resource allocation, packing problems
python examples/knapsack_optimizer.pyClassic 0/1 knapsack problem: maximize value subject to weight capacity.
Project Scheduler (project_scheduler.py)
Constraints: Linear (precedence), optimization
Use Case: Task scheduling with dependencies
python examples/project_scheduler.pyMinimizes project makespan with task precedence constraints.
Advanced Scheduling Constraints
Resource Scheduler (resource_scheduler.py) 🆕
Constraints: Cumulative (resource capacity)
Use Case: CPU/memory allocation, worker scheduling
python examples/resource_scheduler.pySchedules tasks with resource demand under capacity limits. Shows resource utilization timeline.
Delivery Router (delivery_router.py) 🆕
Constraints: Circuit (Hamiltonian path)
Use Case: TSP, vehicle routing, delivery optimization
python examples/delivery_router.pyFinds optimal delivery route visiting all customers with minimum distance.
Inventory Manager (inventory_manager.py) 🆕
Constraints: Reservoir (stock levels)
Use Case: Production/consumption scheduling, inventory management
python examples/inventory_manager.pyManages inventory levels with production and consumption events, maintaining safety stock.
Multi-Objective & AI Orchestration
Multi-Objective Planner (multi_objective_planner.py) 🆕
Constraints: Multi-objective optimization
Use Case: Cloud deployment, trade-off analysis
python examples/multi_objective_planner.pyOptimizes cloud deployment with multiple objectives: minimize cost (priority 1), minimize latency (priority 2).
Tool/Model Selection (tool_selector.py)
Constraints: Implication (conditional logic)
Use Case: MCP tool orchestration, model selection
python examples/tool_selector.pySelects optimal AI models/tools for tasks under budget constraints using implication constraints.
Complex Real-World Examples 🔥
GPU Job Scheduler (gpu_job_scheduler.py) 🆕
Constraints: Resource assignment, memory limits, job dependencies, deadlines, budget
Use Case: ML/AI workload scheduling across heterogeneous GPUs
python examples/gpu_job_scheduler.pySchedules ML jobs (embedding generation, fine-tuning, inference) across different GPU types (A100, V100, T4) optimizing cost vs time with resource constraints.
Embedding Pipeline Scheduler (embedding_pipeline_scheduler.py) 🆕
Constraints: Multi-stage pipeline, rate limits, throughput constraints
Use Case: Document processing through embedding extraction pipeline
python examples/embedding_pipeline_scheduler.pyOrchestrates document batches through preprocessing → embedding → vector DB ingestion, selecting optimal providers (OpenAI, Cohere, Voyage) under rate limits.
ML Pipeline Orchestrator (ml_pipeline_orchestrator.py) 🆕
Constraints: End-to-end pipeline, conditional deployment, quality gates
Use Case: Multi-variant model training with A/B testing
python examples/ml_pipeline_orchestrator.pyTrains multiple model variants through full ML lifecycle (ingest → preprocess → train → eval → deploy), deploys only models meeting quality thresholds.
Example Output
Resource Scheduler Output:
Status: OPTIMAL
Minimum Project Duration: 9 time units
Resource Utilization Timeline:
Time | Utilization | Running Tasks
-----|-------------|------------------
0 | 4/4 ████ | task_B, task_C
1 | 4/4 ████ | task_B, task_C
2 | 3/4 ███ | task_B
4 | 4/4 ████ | task_A, task_D
...Delivery Router Output:
Status: OPTIMAL
Minimum Total Distance: 46 km
Route: Warehouse → Customer_D → Customer_C → Customer_B → Customer_A → WarehouseTool Reference
solve_constraint_model
Solve a general constraint or optimization model.
Parameters:
mode(str):"satisfy"for any feasible solution,"optimize"for best solutionvariables(list): Decision variables with domainsconstraints(list): Constraints to satisfyobjective(dict, optional): Objective function (required if mode is"optimize")search(dict, optional): Search configuration (time limits, etc.)
Variable Schema:
{
"id": "unique_id",
"domain": {
"type": "bool" | "integer",
"lower": 0, # for integer
"upper": 10 # for integer
},
"metadata": {...} # optional
}Constraint Types:
Linear:
sum(coef * var) sense rhs{ "id": "c1", "kind": "linear", "params": { "terms": [{"var": "x", "coef": 2}, {"var": "y", "coef": 3}], "sense": "<=", # "<=", ">=", or "==" "rhs": 10 } }All Different: Variables must have distinct values
{ "id": "c2", "kind": "all_different", "params": {"vars": ["x", "y", "z"]} }Element: Array indexing
target = array[index]{ "id": "c3", "kind": "element", "params": { "index_var": "idx", "array": [10, 20, 30], "target_var": "result" } }Table: Allowed tuples
{ "id": "c4", "kind": "table", "params": { "vars": ["x", "y"], "allowed_tuples": [[0, 1], [1, 0]] } }Implication: If-then constraint
{ "id": "c5", "kind": "implication", "params": { "if_var": "use_feature", "then": { "id": "cost", "kind": "linear", "params": {...} } } }Cumulative: Resource scheduling with capacity
{ "id": "c6", "kind": "cumulative", "params": { "start_vars": ["s1", "s2", "s3"], "duration_vars": [3, 4, 2], # or variable IDs "demand_vars": [2, 1, 3], # or variable IDs "capacity": 5 } }Circuit: Routing/Hamiltonian circuit
{ "id": "c7", "kind": "circuit", "params": { "arcs": [ (0, 1, "arc_0_1"), # (from_node, to_node, bool_var) (1, 2, "arc_1_2"), # ... ] } }Reservoir: Inventory/stock management
{ "id": "c8", "kind": "reservoir", "params": { "time_vars": ["t1", "t2", "t3"], "level_changes": [5, -3, -2], # production/consumption "min_level": 0, "max_level": 10 } }No-Overlap: Disjunctive scheduling
{ "id": "c9", "kind": "no_overlap", "params": { "start_vars": ["s1", "s2", "s3"], "duration_vars": [3, 4, 2] # or variable IDs } }
Multi-Objective Optimization:
{
"mode": "optimize",
"objective": [
{
"sense": "max",
"terms": [{"var": "x", "coef": 1}],
"priority": 2, # Higher priority
"weight": 1.0
},
{
"sense": "max",
"terms": [{"var": "y", "coef": 1}],
"priority": 1, # Lower priority
"weight": 1.0
}
]
}Search Configuration:
{
"search": {
"max_time_ms": 5000,
"max_solutions": 1,
"num_search_workers": 4,
"log_search_progress": false,
"random_seed": 42, # Deterministic solving
"strategy": "first_fail", # Search strategy hint
"return_partial_solution": true, # Return best-so-far on timeout
"enable_solution_caching": true, # Cache solutions
"warm_start_solution": {"x": 5, "y": 3}
}
}Search Strategies:
"auto"(default): Let solver choose best strategy"first_fail": Choose variables with smallest domain first"largest_first": Choose variables with largest domain first"random": Random variable selection"cheapest_first": Choose least expensive variables first
Solution Caching:
The solver automatically caches solutions using problem hashing to avoid re-solving identical problems. Enable/disable with enable_solution_caching (default: true).
# First solve - hits the solver
response1 = await solver.solve_constraint_model(request)
# Identical problem - returns cached solution
response2 = await solver.solve_constraint_model(request) # Cache hit!Cache uses LRU eviction (max 1000 entries) with 1-hour TTL. Access global cache stats:
from chuk_mcp_solver.cache import get_global_cache
cache = get_global_cache()
stats = cache.stats()
# {'size': 42, 'max_size': 1000, 'hits': 15, 'misses': 27, 'hit_rate_pct': 35.71, 'ttl_seconds': 3600}Partial Solutions on Timeout:
When solving complex problems with time limits, enable return_partial_solution to get the best solution found so far:
{
"mode": "optimize",
"search": {
"max_time_ms": 1000, # 1 second limit
"return_partial_solution": true
},
# ... variables, constraints, objective ...
}If timeout occurs, you'll get a FEASIBLE solution with a note explaining it's the best found so far.
Validation and Error Messages:
The solver validates models before solving and provides actionable error messages to help LLMs self-correct:
# Invalid model with typo
response = await solver.solve_constraint_model({
"mode": "optimize",
"variables": [{"id": "x", "domain": {"type": "integer", "lower": 0, "upper": 10}}],
"constraints": [{
"id": "c1",
"kind": "linear",
"params": {
"terms": [{"var": "y", "coef": 1}], # Typo: 'y' instead of 'x'
"sense": "<=",
"rhs": 5
}
}],
"objective": {"sense": "max", "terms": [{"var": "x", "coef": 1}]}
})
# Response includes helpful error:
# status: ERROR
# explanation: "Model validation failed with 1 error(s):
# 1. Variable 'y' referenced in constraint 'c1' is not defined
# Location: constraint[c1].params.terms[0].var
# Suggestion: Did you mean 'x'? (defined variables: x)"Validation checks:
Undefined variables (with "did you mean?" suggestions)
Duplicate IDs
Invalid domain bounds
Empty constraint sets
Objective without variables
Type mismatches
Response Schema:
{
"status": "optimal" | "feasible" | "satisfied" | "infeasible" | "unbounded" | "timeout_best" | "timeout_no_solution" | "error",
"objective_value": 42.0, # if applicable
"optimality_gap": 0.0, # % gap from best bound (0 = proven optimal)
"solve_time_ms": 1234, # actual wall-clock solve time
"solutions": [
{
"variables": [
{"id": "x", "value": 5, "metadata": {...}}
],
"derived": {...} # optional computed metrics
}
],
"explanation": {
"summary": "Found optimal solution...",
"binding_constraints": [...] # tight constraints
}
}Status Codes:
optimal: Proven optimal solution foundfeasible: Valid solution found, but may not be optimalsatisfied: All constraints satisfied (for satisfy mode)infeasible: No solution existsunbounded: Objective can be improved infinitelytimeout_best: Timeout reached, returning best solution found so fartimeout_no_solution: Timeout reached before finding any solutionerror: Solver error occurred
Performance Metrics:
optimality_gap: Percentage gap from best bound (0.0 for optimal solutions)solve_time_ms: Actual wall-clock time spent solving
solve_scheduling_problem
🆕 High-Level Scheduling API - A simpler interface for task scheduling problems that automatically builds the CP-SAT model for you.
Use this instead of solve_constraint_model when you have tasks with durations, dependencies, and resource constraints. Perfect for project planning, job scheduling, and resource allocation.
Parameters:
tasks(list): Tasks to schedule, each with:id(str): Unique task identifierduration(int): Task duration in time unitsresources_required(dict, optional):{resource_id: amount}mappingdependencies(list, optional): Task IDs that must complete firstearliest_start(int, optional): Release time (can't start before this)deadline(int, optional): Due date (must finish by this)priority(int, optional): Task priority (default 1)metadata(dict, optional): Custom metadata preserved in response
resources(list, optional): Resources with capacity limits:id(str): Resource identifiercapacity(int): Maximum units available at any timecost_per_unit(float, optional): Cost per unit-timemetadata(dict, optional): Custom metadata
objective(str): Optimization goal"minimize_makespan"(default): Minimize total project duration"minimize_cost": Minimize total resource cost"minimize_lateness": Minimize lateness/tardiness
max_time_ms(int, optional): Maximum solver time in milliseconds (default: 60000)
Response:
{
"status": "optimal" | "feasible" | "infeasible" | "timeout_best" | "timeout_no_solution" | "error",
"makespan": 42, # Total project completion time
"total_cost": 123.45, # Total cost (if minimize_cost)
"schedule": [
{
"task_id": "build",
"start_time": 0,
"end_time": 10,
"resources_used": {"cpu": 2},
"on_critical_path": true,
"slack": 0,
"metadata": {...} # preserved from request
},
# ... more tasks
],
"resource_utilization": [
{
"resource_id": "cpu",
"peak_usage": 4,
"average_usage": 2.5,
"utilization_pct": 62.5
}
],
"critical_path": ["build", "test", "deploy"],
"solve_time_ms": 234,
"optimality_gap": 0.0,
"explanation": {
"summary": "Found optimal schedule completing in 42 time units with 10 tasks using 3 resources",
"recommendations": [] # suggestions if infeasible
}
}Example: Simple Project Schedule
response = await solve_scheduling_problem(
tasks=[
{"id": "build", "duration": 10},
{"id": "test", "duration": 5, "dependencies": ["build"]},
{"id": "deploy", "duration": 3, "dependencies": ["test"]},
],
objective="minimize_makespan"
)
# Returns: makespan=18, schedule with optimal timingsExample: Resource-Constrained Scheduling
response = await solve_scheduling_problem(
tasks=[
{"id": "task_a", "duration": 5, "resources_required": {"cpu": 2}},
{"id": "task_b", "duration": 3, "resources_required": {"cpu": 3}},
{"id": "task_c", "duration": 4, "resources_required": {"cpu": 1}},
],
resources=[{"id": "cpu", "capacity": 4}],
objective="minimize_makespan"
)
# Automatically handles resource capacity constraints using cumulative constraintsExample: Deadlines and Release Times
response = await solve_scheduling_problem(
tasks=[
{"id": "prep", "duration": 2, "earliest_start": 0},
{"id": "main", "duration": 6, "dependencies": ["prep"], "deadline": 10},
{"id": "review", "duration": 3, "dependencies": ["main"], "earliest_start": 8},
],
objective="minimize_makespan"
)
# Handles time windows and deadlines automaticallyWhen to Use This vs. solve_constraint_model:
✅ Use solve_scheduling_problem when:
You have tasks with durations and dependencies
You need to manage resource capacities
You want to minimize makespan/cost/lateness
You want a simpler, domain-specific API
🔧 Use solve_constraint_model when:
You need custom constraints beyond scheduling
You're solving non-scheduling problems (puzzles, knapsack, etc.)
You need fine-grained control over the model
You're combining scheduling with other constraint types
Behind the Scenes:
This tool automatically converts your high-level scheduling problem into a CP-SAT model with:
Start/end time variables for each task
Duration constraints:
end = start + durationPrecedence constraints for dependencies
Cumulative constraints for resource capacity
Deadline constraints
Makespan variable and objective
See scheduling_demo.py for comprehensive examples.
solve_routing_problem
🆕 High-Level Routing API - A simpler interface for TSP and VRP problems that automatically builds the CP-SAT model for you.
Use this instead of solve_constraint_model when you need to find optimal routes for vehicles visiting locations. Perfect for delivery routing, traveling salesman problems, and logistics optimization.
Parameters:
locations(list): Locations to visit, each with:id(str): Unique location identifiercoordinates(tuple, optional): (x, y) or (lat, lon) coordinatesservice_time(int, optional): Time spent at location (default 0)time_window(tuple, optional): (earliest, latest) arrival timedemand(int, optional): Demand at location for capacity constraintspriority(int, optional): Location priority (default 1)
vehicles(list, optional): Vehicles (if empty, assumes single vehicle TSP):id(str): Vehicle identifiercapacity(int, optional): Maximum load (default 999999)start_location(str): Starting location IDend_location(str, optional): Ending location if different from startmax_distance(int, optional): Maximum distance vehicle can travelmax_time(int, optional): Maximum time vehicle can be in usecost_per_distance(float, optional): Cost per unit distance (default 1.0)fixed_cost(float, optional): Fixed cost if vehicle is used (default 0.0)
distance_matrix(list[list[int]], optional): Distance matrix where [i][j] = distance from location i to j. If not provided, uses Euclidean distance from coordinates.objective(str): Optimization goal"minimize_distance"(default): Minimize total distance"minimize_time": Minimize total time"minimize_vehicles": Use fewest vehicles"minimize_cost": Minimize total cost
max_time_ms(int, optional): Maximum solver time in milliseconds (default: 60000)
Response:
{
"status": "optimal" | "feasible" | "infeasible" | "timeout_best" | "timeout_no_solution" | "error",
"routes": [
{
"vehicle_id": "truck_1",
"sequence": ["depot", "customer_A", "customer_B", "depot"],
"total_distance": 45,
"total_time": 55, # including service times
"total_cost": 112.50,
"load_timeline": [] # for capacity-constrained routing
}
],
"unvisited": [], # locations not visited (if force_visit_all=False)
"total_distance": 45,
"total_time": 55,
"total_cost": 112.50,
"vehicles_used": 1,
"solve_time_ms": 123,
"optimality_gap": 0.0,
"explanation": {
"summary": "Found optimal route visiting 4 locations with total distance 45",
"bottlenecks": [],
"recommendations": []
}
}Example: Simple TSP with Coordinates
response = await solve_routing_problem(
locations=[
{"id": "warehouse", "coordinates": (0, 0)},
{"id": "customer_A", "coordinates": (10, 5)},
{"id": "customer_B", "coordinates": (5, 10)},
{"id": "customer_C", "coordinates": (15, 15)},
],
objective="minimize_distance"
)
# Returns optimal tour visiting all locationsExample: TSP with Distance Matrix
response = await solve_routing_problem(
locations=[
{"id": "A"},
{"id": "B"},
{"id": "C"},
],
distance_matrix=[
[0, 10, 20],
[10, 0, 15],
[20, 15, 0],
],
objective="minimize_distance"
)
# Uses provided distances instead of coordinatesExample: Routing with Service Times and Costs
response = await solve_routing_problem(
locations=[
{"id": "depot", "coordinates": (0, 0), "service_time": 0},
{"id": "store_A", "coordinates": (10, 0), "service_time": 15},
{"id": "store_B", "coordinates": (10, 10), "service_time": 20},
],
vehicles=[
{
"id": "van_1",
"start_location": "depot",
"cost_per_distance": 2.5,
"fixed_cost": 50.0
}
],
objective="minimize_cost"
)
# Minimizes total cost (fixed + distance * cost_per_distance)When to Use This vs. solve_constraint_model:
✅ Use solve_routing_problem when:
You need to find optimal routes for visiting locations
You have TSP (Traveling Salesman Problem) scenarios
You want to optimize delivery routes
You want a simpler, domain-specific API
🔧 Use solve_constraint_model when:
You need custom constraints beyond routing
You're solving non-routing problems
You need fine-grained control over the circuit constraint
You're combining routing with other constraint types
Behind the Scenes:
This tool automatically converts your high-level routing problem into a CP-SAT model with:
Boolean arc variables for each possible location-to-location connection
Multi-vehicle support with flow conservation and MTZ subtour elimination ✨ NEW
Capacity constraints for vehicle load limits ✨ NEW
Circuit constraint for single-vehicle TSP (Hamiltonian tour)
Distance/time/cost/vehicles objective functions
Support for service times at locations
Vehicle cost modeling (fixed + per-distance)
Load timeline tracking for capacity-constrained routing ✨ NEW
Supported Features:
✅ Single-vehicle TSP (Traveling Salesman Problem) ✅ Multi-vehicle VRP (Vehicle Routing Problem) with capacity constraints ✨ NEW (Phase 1) ✅ Multiple optimization objectives: minimize_distance, minimize_time, minimize_cost, minimize_vehicles ✅ Service times at locations ✅ Vehicle-specific costs (fixed + per-distance) ✅ Demand/capacity constraints
Current Limitations:
No time window constraints yet
No pickup and delivery yet
No heterogeneous fleets (different vehicle types with different capabilities)
See routing_demo.py for comprehensive examples.
solve_budget_allocation 🆕
High-level interface for budget allocation and knapsack problems.
Solves portfolio selection, feature prioritization, and resource allocation problems. Automatically handles dependencies, conflicts, and multiple resource constraints.
Parameters:
items(list[dict]): Items to choose from, each with:id(str): Unique identifiercost(float): Cost of selecting this itemvalue(float): Value/benefit (ROI, utility, priority)resources_required(dict, optional): Multi-resource requirements like{"headcount": 2, "time": 3}dependencies(list, optional): Item IDs that must also be selectedconflicts(list, optional): Item IDs that cannot be selected together
budgets(list[dict]): Resource constraints, each with:resource(str): Resource name (e.g., "money", "time", "headcount")limit(float): Maximum available
objective(str): Goal -"maximize_value"(default),"maximize_count", or"minimize_cost"min_value_threshold(float, optional): Minimum total value requiredmax_cost_threshold(float, optional): Maximum total cost allowedmin_items(int, optional): Minimum number of items to selectmax_items(int, optional): Maximum number of items to selectmax_time_ms(int): Maximum solver time (default: 60000)
Response:
{
"status": "optimal",
"selected_items": ["project_A", "project_C"],
"total_cost": 9000.0,
"total_value": 21000.0,
"resource_usage": {"money": 9000.0},
"resource_slack": {"money": 1000.0},
"solve_time_ms": 5,
"optimality_gap": null,
"explanation": {
"summary": "Optimal selection: 2 items with total value 21000.00 under budget of 9000.00",
"binding_constraints": ["Budget 'money' has 1000.00 slack (10.0%)"],
"marginal_items": [],
"recommendations": []
}
}Example 1: Simple Knapsack
response = await solve_budget_allocation(
items=[
{"id": "project_A", "cost": 5000, "value": 12000},
{"id": "project_B", "cost": 3000, "value": 7000},
{"id": "project_C", "cost": 4000, "value": 9000},
],
budgets=[
{"resource": "money", "limit": 10000}
],
objective="maximize_value"
)
# Returns: Optimal selection maximizing value under $10k budgetExample 2: With Dependencies
response = await solve_budget_allocation(
items=[
{"id": "backend", "cost": 8000, "value": 5000},
{"id": "frontend", "cost": 6000, "value": 12000,
"dependencies": ["backend"]}, # Frontend requires backend
{"id": "mobile", "cost": 7000, "value": 10000,
"dependencies": ["backend"]},
],
budgets=[{"resource": "money", "limit": 15000}],
objective="maximize_value"
)
# Automatically ensures dependencies are satisfiedExample 3: With Conflicts
response = await solve_budget_allocation(
items=[
{"id": "mobile_checkout", "cost": 5000, "value": 15000,
"conflicts": ["web_redesign"]}, # Can't do both
{"id": "web_redesign", "cost": 6000, "value": 14000,
"conflicts": ["mobile_checkout"]},
{"id": "analytics", "cost": 3000, "value": 8000},
],
budgets=[{"resource": "money", "limit": 12000}],
objective="maximize_value"
)
# Ensures conflicting items are not both selectedExample 4: Multi-Resource
response = await solve_budget_allocation(
items=[
{"id": "feature_A", "cost": 5000, "value": 10000,
"resources_required": {"headcount": 2, "time": 3}},
{"id": "feature_B", "cost": 3000, "value": 7000,
"resources_required": {"headcount": 1, "time": 2}},
],
budgets=[
{"resource": "money", "limit": 10000},
{"resource": "headcount", "limit": 3},
{"resource": "time", "limit": 4}
],
objective="maximize_value"
)
# Respects all resource constraints simultaneouslyWhen to Use:
✅ Use solve_budget_allocation when:
You need to select items under budget constraints
You have knapsack or portfolio selection problems
You need to handle dependencies or conflicts between items
You have multiple resource constraints (budget, time, headcount)
You want to maximize value, minimize cost, or maximize count
🔧 Use solve_constraint_model when:
You need custom constraints beyond allocation
You're solving non-allocation problems
You need fine-grained control over the knapsack formulation
You're combining allocation with other constraint types
Behind the Scenes:
This tool automatically converts your high-level allocation problem into a CP-SAT model with:
Binary selection variables for each item
Linear budget constraints for each resource
Implication constraints for dependencies (if A then B)
Linear constraints for conflicts (A + B ≤ 1)
Value/cost/count objective function
Optional min/max value, cost, and item count constraints
Current Limitations:
No soft budget constraints (penalty-based) yet
No category-based selection rules yet
No multi-period allocation yet
See allocation_demo.py for comprehensive examples.
solve_assignment_problem 🆕
High-level task-to-agent assignment interface - Automatically builds CP-SAT models for assigning tasks to agents with skill matching, capacity constraints, and load balancing.
response = await solve_assignment_problem(
agents=[...],
tasks=[...],
objective="minimize_cost" | "maximize_assignments" | "balance_load",
cost_matrix=None, # Optional: Custom cost matrix
force_assign_all=True, # Require all tasks assigned
max_time_ms=60000,
)Example 1: Simple Assignment (Minimize Cost)
response = await solve_assignment_problem(
agents=[
{"id": "alice", "capacity": 2, "cost_multiplier": 1.0}, # $50/hour
{"id": "bob", "capacity": 2, "cost_multiplier": 1.5}, # $75/hour
],
tasks=[
{"id": "task_1", "duration": 2}, # 2 hours
{"id": "task_2", "duration": 3}, # 3 hours
{"id": "task_3", "duration": 1}, # 1 hour
],
objective="minimize_cost",
)
# Assigns tasks to cheapest agents: alice gets task_1 + task_2, bob gets task_3
# Total cost: $325 (alice: $100 + $150, bob: $75)Example 2: Skill Matching
response = await solve_assignment_problem(
agents=[
{"id": "alice", "capacity": 2, "skills": ["python", "docker", "aws"]},
{"id": "bob", "capacity": 2, "skills": ["react", "typescript", "nodejs"]},
{"id": "charlie", "capacity": 2, "skills": ["python", "react", "postgres"]},
],
tasks=[
{"id": "backend_api", "duration": 5, "required_skills": ["python", "docker"]},
{"id": "frontend_ui", "duration": 4, "required_skills": ["react", "typescript"]},
{"id": "database_migration", "duration": 2, "required_skills": ["python", "postgres"]},
{"id": "deployment", "duration": 3, "required_skills": ["docker", "aws"]},
],
objective="minimize_cost",
)
# Only assigns tasks to agents with matching skills
# backend_api → alice, frontend_ui → bob, database_migration → charlie, deployment → aliceExample 3: Load Balancing
response = await solve_assignment_problem(
agents=[
{"id": "server_1", "capacity": 5},
{"id": "server_2", "capacity": 5},
{"id": "server_3", "capacity": 5},
],
tasks=[{"id": f"job_{i}", "duration": 1} for i in range(9)],
objective="balance_load",
)
# Distributes tasks evenly: each server gets exactly 3 tasksExample 4: Maximize Assignments (Optional Tasks)
response = await solve_assignment_problem(
agents=[
{"id": "team_member_1", "capacity": 2},
{"id": "team_member_2", "capacity": 2},
],
tasks=[
{"id": "feature_a", "duration": 1},
{"id": "feature_b", "duration": 1},
{"id": "feature_c", "duration": 1},
{"id": "feature_d", "duration": 1},
{"id": "feature_e", "duration": 1},
],
objective="maximize_assignments",
force_assign_all=False, # Some tasks can remain unassigned
)
# Assigns 4 out of 5 tasks (capacity limit)
# Returns unassigned_tasks: ["feature_c"]When to Use:
✅ Use solve_assignment_problem when:
You need to assign tasks to agents/workers/servers
You have skill or qualification requirements
You need to respect capacity or workload limits
You want to minimize cost, maximize assignments, or balance load
You have custom task-agent costs or preferences
🔧 Use solve_constraint_model when:
You need custom constraints beyond assignment
You're solving non-assignment problems
You need fine-grained control over the assignment formulation
You're combining assignment with other constraint types
Behind the Scenes:
This tool automatically converts your high-level assignment problem into a CP-SAT model with:
Binary assignment variables for each (task, agent) pair
Task assignment constraints (each task to exactly one agent, or at most one if optional)
Agent capacity constraints (max number of tasks per agent)
Skill matching constraints (forbid incompatible assignments)
Cost minimization, assignment maximization, or load balancing objective
Automatic cost matrix generation from agent cost_multiplier and task duration
Response Fields:
response.status # SolverStatus.OPTIMAL, FEASIBLE, INFEASIBLE, etc.
response.assignments # List[Assignment(task_id, agent_id, cost)]
response.unassigned_tasks # List[str] - Tasks not assigned (if force_assign_all=False)
response.agent_load # Dict[str, int] - Number of tasks per agent
response.total_cost # float - Total assignment cost
response.solve_time_ms # int - Solve time in milliseconds
response.optimality_gap # Optional[float] - Gap to optimal (if timeout)
response.explanation # AssignmentExplanation with summary and recommendations
response.explanation.overloaded_agents # List[str] - Agents with >150% of average load
response.explanation.underutilized_agents # List[str] - Agents with <50% of average loadCurrent Limitations:
No multi-skill level support (e.g., junior vs senior) yet
No task priority or preemption yet
No time windows or deadlines yet
No agent preferences or task affinity yet
See assignment_demo.py for comprehensive examples.
Configuration
Environment Variables
# Provider selection
export CHUK_SOLVER_PROVIDER=ortools
# Tool-specific provider
export CHUK_SOLVER_TOOL_PROVIDER=ortools
# Config file location
export CHUK_SOLVER_CONFIG=/path/to/config.yamlYAML Configuration
Create ~/.config/chuk-mcp-solver/config.yaml:
default_provider: ortools
tool_providers:
solve_constraint_model: ortoolsDevelopment
Setup
# Clone repository
git clone https://github.com/chuk-ai/chuk-mcp-solver.git
cd chuk-mcp-solver
# Install with dev dependencies
uv pip install -e ".[dev]"Testing
# Run tests
make test
# Run with coverage (requires 90%+)
make test-cov
# Run specific tests
pytest tests/test_models.py -v
# Current stats: 196 tests, 93% coverage ✅Code Quality
# Lint
make lint
# Format
make format
# Type check
make typecheck
# All checks
make checkRunning Locally
# Run server
make run
# Or directly
python -m chuk_mcp_solver.serverArchitecture
chuk-mcp-solver/
├── src/chuk_mcp_solver/
│ ├── __init__.py # Package metadata
│ ├── server.py # MCP server + tools
│ ├── models.py # Pydantic models + enums
│ ├── config.py # Configuration management
│ ├── validation.py # 🆕 Model validation (Phase 2)
│ ├── cache.py # 🆕 Solution caching (Phase 3)
│ ├── observability.py # 🆕 Logging & metrics (Phase 1)
│ ├── diagnostics.py # 🆕 Health checks & analysis (Phase 1)
│ └── solver/ # Solver implementations
│ ├── __init__.py # Solver factory (get_solver)
│ ├── provider.py # Abstract solver interface
│ └── ortools/ # OR-Tools implementation
│ ├── solver.py # Main ORToolsSolver class
│ ├── constraints.py # Constraint builders
│ ├── objectives.py # Objective + search config
│ ├── responses.py # Response builders
│ └── scheduling.py # 🆕 High-level scheduling converters (Phase 4)
├── tests/ # Comprehensive test suite (196 tests)
│ ├── test_solver.py # Factory tests
│ ├── test_models.py # Model validation tests
│ ├── test_validation.py # 🆕 Validation framework tests
│ ├── test_cache.py # 🆕 Caching tests
│ ├── test_performance.py # 🆕 Performance feature tests
│ ├── test_observability.py # 🆕 Observability tests
│ ├── test_diagnostics.py # 🆕 Diagnostics tests
│ ├── test_scheduling.py # 🆕 High-level scheduling tests (Phase 4)
│ └── solver/ortools/ # OR-Tools tests (mirrors source)
│ ├── test_solver.py
│ ├── test_constraints.py
│ ├── test_responses.py
│ └── test_edge_cases.py
├── examples/ # Example scripts (13 examples)
└── pyproject.toml # Package configurationKey Design Patterns:
Modular Architecture: Focused modules with single responsibilities
Solver Pattern: Pluggable solver backends via abstract interface
Factory Function: Simple
get_solver()for solver instantiationPydantic Models: Type-safe throughout
Async Native: Non-blocking I/O
No Magic Strings: Enums for all constants
Mirrored Test Structure: Tests match source organization
Use Cases
Scheduling & Resource Allocation
Project Scheduling: Task scheduling with precedence constraints →
project_scheduler.pyResource-Constrained Scheduling: CPU/memory/worker allocation with capacity limits →
resource_scheduler.pyInventory Management: Production/consumption planning with stock levels →
inventory_manager.pyShift Rostering: Employee scheduling with availability and skill constraints
Meeting Scheduling: Calendar optimization with participant constraints
Routing & Logistics
Vehicle Routing: Delivery route optimization (TSP/VRP) →
delivery_router.pyCircuit Planning: Hamiltonian path/circuit problems
Network Design: Optimal path selection in graphs
Warehouse Optimization: Pick path optimization
Optimization Problems
Knapsack Problems: Resource allocation under weight/capacity limits →
knapsack_optimizer.pyBudget Allocation: Optimal spending across categories
Portfolio Selection: Asset selection under risk/return constraints
Packing Problems: Bin packing, cutting stock
AI/LLM Orchestration
Multi-Model Selection: Choose optimal AI models under budget →
tool_selector.pyMulti-Objective Planning: Balance cost, latency, quality trade-offs →
multi_objective_planner.pyRate-Limit Aware Scheduling: Task scheduling respecting API limits
Capability-Based Routing: Route requests to appropriate models
Cost-Latency Optimization: Minimize cost while meeting SLAs
Configuration & Selection
System Configuration: Parameter optimization under constraints
Feature Selection: Optimal feature subset selection
Bundle Recommendations: Best product/service combinations
Resource Sizing: Cloud instance selection and sizing
Logic Puzzles
Sudoku: Constraint satisfaction puzzles →
sudoku_solver.pyKakuro, KenKen: Arithmetic constraint puzzles
Logic Grids: Deductive reasoning puzzles
N-Queens: Placement problems
Roadmap
Phase 1: Trust & Foundations ✅ (Completed)
Structured observability and logging
Health checks and diagnostics
Problem hashing for deduplication
Infeasibility diagnosis
Deterministic solving (random seeds)
Solution metadata tracking
Phase 2: Developer Experience ✅ (Completed)
Pre-solve model validation
Actionable error messages for LLMs
Smart typo detection ("Did you mean...?")
Three-level validation severity (ERROR, WARNING, INFO)
Detailed validation suggestions
Phase 3: Power & Performance ✅ (Completed)
Solution caching with LRU + TTL
Partial solutions (best-so-far on timeout)
Search strategy hints (first-fail, random, etc.)
Cache statistics and hit rate tracking
Warm-start solution hints
Phase 1-3 Foundation Features ✅
Cumulative constraints (resource scheduling)
Circuit constraints (routing/TSP)
Reservoir constraints (inventory management)
No-overlap constraints (disjunctive scheduling)
Multi-objective optimization (priority-based)
Parallel search workers
Search progress logging
Phase 4: LLM-Native Problem Schemas 🚧 (In Progress)
Completed:
High-level scheduling API (
solve_scheduling_problem)Task model with dependencies, resources, deadlines
Resource model with capacity constraints
Automatic CP-SAT model generation from high-level specs
Rich scheduling responses (makespan, critical path, utilization)
Scheduling examples and documentation
High-level routing API (TSP/VRP) ✨ NEW
Multi-vehicle VRP with capacity constraints ✨ NEW (Phase 4.1)
MTZ subtour elimination for VRP ✨ NEW
Multiple optimization objectives (distance, time, cost, vehicles) ✨ NEW
Load timeline tracking ✨ NEW
VRP examples and documentation ✨ NEW
High-level budget allocation API
High-level assignment API
In Progress:
Time window constraints for VRP
Pickup and delivery for VRP
Heterogeneous fleet support
Phase 5-7: Planned 🔮
Solution enumeration (find N diverse solutions)
Solution visualization (Gantt charts, graphs)
Enhanced debugging (conflict analysis)
Export to MPS/LP formats
Advanced search strategies (custom heuristics)
Symmetry breaking
Decomposition strategies
Documentation generation from models
Contributing
Contributions welcome! Please:
Fork the repository
Create a feature branch
Add tests for new functionality
Ensure
make checkpassesSubmit a pull request
License
MIT License - see LICENSE for details.
License
Apache License 2.0 - see LICENSE for details.
This is a demonstration project provided as-is for learning and testing purposes.
Acknowledgments
Built with:
Google OR-Tools - CP-SAT solver
Pydantic - Data validation
Model Context Protocol - Protocol specification
Available Tools
5 toolssolve_assignment_problemA
Solve a task assignment problem.
This is a high-level interface for assignment and matching problems. Use this instead of solve_constraint_model when you need to assign tasks to agents/workers with capacity and skill constraints.
Args: agents: List of agents available to perform tasks, each with: - id (str): Unique agent identifier - capacity (int, optional): Maximum number of tasks (default 1) - skills (list, optional): Skills this agent possesses - cost_multiplier (float, optional): Cost multiplier (default 1.0) - metadata (dict, optional): Additional context tasks: List of tasks to be assigned, each with: - id (str): Unique task identifier - required_skills (list, optional): Skills required for this task - duration (int, optional): Task duration/workload (default 1) - priority (int, optional): Task priority (default 1) - metadata (dict, optional): Additional context cost_matrix: Optional cost matrix where [i][j] = cost to assign task i to agent j. If not provided, uses agent.cost_multiplier * task.duration objective: Optimization goal - 'minimize_cost', 'maximize_assignments', or 'balance_load' force_assign_all: If True, all tasks must be assigned (infeasible if not possible). If False, some tasks can remain unassigned. max_time_ms: Maximum solver time in milliseconds (default 60000)
Returns: SolveAssignmentProblemResponse containing: - status: Solution status - assignments: List of task-to-agent assignments - unassigned_tasks: Tasks that could not be assigned - agent_load: Number of tasks assigned to each agent - total_cost: Total cost of all assignments - solve_time_ms: Actual solve time - optimality_gap: Gap from best bound - explanation: Human-readable summary
Tips for LLMs: - For task assignment: agents are workers/machines, tasks are jobs/work items - For matching: agents are resources, tasks are requests to match - Skills create hard constraints (incompatible if skills don't match) - Use minimize_cost for cost-optimal assignments - Use maximize_assignments when some tasks are optional - Use balance_load to distribute work evenly across agents
Example (Simple Assignment)::
response = await solve_assignment_problem(
agents=[
{"id": "worker_1", "capacity": 2, "cost_multiplier": 1.0},
{"id": "worker_2", "capacity": 2, "cost_multiplier": 1.5},
],
tasks=[
{"id": "task_A", "duration": 3},
{"id": "task_B", "duration": 2},
{"id": "task_C", "duration": 1},
],
objective="minimize_cost"
)
# Returns cost-optimal assignment respecting capacityExample (With Skills)::
response = await solve_assignment_problem(
agents=[
{"id": "dev_1", "capacity": 3, "skills": ["python", "docker"]},
{"id": "dev_2", "capacity": 2, "skills": ["python", "react"]},
],
tasks=[
{"id": "backend", "duration": 5, "required_skills": ["python", "docker"]},
{"id": "frontend", "duration": 4, "required_skills": ["react"]},
],
objective="minimize_cost"
)
# Only assigns tasks to agents with matching skillsExample (Balance Load)::
response = await solve_assignment_problem(
agents=[
{"id": "server_1", "capacity": 10},
{"id": "server_2", "capacity": 10},
{"id": "server_3", "capacity": 10},
],
tasks=[
{"id": f"job_{i}", "duration": 1} for i in range(15)
],
objective="balance_load"
)
# Distributes tasks evenly across servers (5 per server)
| Name | Required | Description | Default |
|---|---|---|---|
| tasks | Yes | ||
| agents | Yes | ||
| objective | No | minimize_cost | |
| cost_matrix | No | ||
| max_time_ms | No | ||
| force_assign_all | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully discloses behavioral traits: it describes the optimization behavior (minimize_cost, maximize_assignments, balance_load), hard constraints from skills, forced assignment behavior, default cost matrix logic, solver timeout, and return values. It also explains that skills create hard constraints and provides agent load distribution details.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections (purpose, usage, args, returns, tips, examples). While lengthy, every sentence adds value and the information is front-loaded. It avoids redundancy but could be slightly more concise without losing effectiveness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description is complete for a complex tool: it covers parameter semantics, behavioral constraints, return values (including a structured response object), usage scenarios, and example code. No output schema exists, but the description compensates by listing response fields. It addresses potential edge cases (force_assign_all, unassigned tasks) and provides LLM tips.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Despite the schema description coverage being 0%, the description provides detailed explanations for all 6 parameters: agents, tasks, cost_matrix, objective, force_assign_all, max_time_ms. It includes default values, structure of nested objects, and examples that clarify usage. This adds significant meaning beyond the schema items' basic descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Solve a task assignment problem' and distinguishes from sibling tools by specifying 'Use this instead of solve_constraint_model when you need to assign tasks to agents/workers with capacity and skill constraints.' It also mentions alternatives like solve_budget_allocation and solve_routing_problem implicitly through the sibling list.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance on when to use this tool ('Use this instead of solve_constraint_model'), and includes context for LLMs with tips on assignment vs matching, skill constraints, and objective selection. It also gives examples demonstrating different scenarios (simple assignment, with skills, balance load), reinforcing usage guidelines.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
solve_budget_allocationA
Solve a budget allocation or knapsack problem.
This is a high-level interface for budget allocation and portfolio selection problems. Use this instead of solve_constraint_model when you need to select items under budget constraints with dependencies and conflicts.
Args: items: List of items to choose from, each with: - id (str): Unique item identifier - cost (float): Cost of selecting this item - value (float): Value/benefit of this item (ROI, utility, priority score) - resources_required (dict, optional): {resource_name: amount} dict for multi-resource constraints - dependencies (list, optional): Item IDs that must also be selected if this item is selected - conflicts (list, optional): Item IDs that cannot be selected together with this item - metadata (dict, optional): Additional context budgets: List of budget constraints, each with: - resource (str): Resource name (e.g., "money", "time", "headcount") - limit (float): Maximum amount available - penalty_per_unit_over (float, optional): Penalty for exceeding (default 0 = hard constraint) objective: Optimization goal - 'maximize_value', 'maximize_count', or 'minimize_cost' min_value_threshold: Optional minimum total value required max_cost_threshold: Optional maximum total cost allowed min_items: Optional minimum number of items to select max_items: Optional maximum number of items to select max_time_ms: Maximum solver time in milliseconds (default 60000)
Returns: SolveBudgetAllocationResponse containing: - status: Solution status - selected_items: List of selected item IDs - total_cost: Total cost of selected items - total_value: Total value of selected items - resource_usage: Resource consumption by resource name - resource_slack: Unused capacity by resource name - solve_time_ms: Actual solve time - optimality_gap: Gap from best bound - explanation: Human-readable summary
Tips for LLMs: - For portfolio selection: items are projects/investments, budgets are capital/resources - For feature prioritization: items are features, value is business value, cost is effort - For campaign allocation: items are campaigns, budgets are ad spend across channels - Dependencies model "must have both or neither" relationships - Conflicts model "can only choose one" relationships - Use maximize_value for ROI optimization - Use maximize_count to get as many items as possible under budget
Example (Simple Knapsack)::
response = await solve_budget_allocation(
items=[
{"id": "project_A", "cost": 5000, "value": 12000},
{"id": "project_B", "cost": 3000, "value": 7000},
{"id": "project_C", "cost": 4000, "value": 9000},
],
budgets=[
{"resource": "money", "limit": 10000}
],
objective="maximize_value"
)
# Returns optimal selection maximizing value under $10k budgetExample (With Dependencies)::
response = await solve_budget_allocation(
items=[
{"id": "backend", "cost": 8000, "value": 5000},
{"id": "frontend", "cost": 6000, "value": 8000, "dependencies": ["backend"]},
{"id": "mobile", "cost": 7000, "value": 6000, "dependencies": ["backend"]},
],
budgets=[
{"resource": "money", "limit": 15000}
],
objective="maximize_value"
)
# Frontend requires backend, so solver considers dependenciesExample (Multi-Resource)::
response = await solve_budget_allocation(
items=[
{"id": "feature_A", "cost": 5000, "value": 10000,
"resources_required": {"headcount": 2, "time": 3}},
{"id": "feature_B", "cost": 3000, "value": 7000,
"resources_required": {"headcount": 1, "time": 2}},
],
budgets=[
{"resource": "money", "limit": 10000},
{"resource": "headcount", "limit": 3},
{"resource": "time", "limit": 4}
],
objective="maximize_value"
)
# Respects multiple resource constraints simultaneously
| Name | Required | Description | Default |
|---|---|---|---|
| items | Yes | ||
| budgets | Yes | ||
| max_items | No | ||
| min_items | No | ||
| objective | No | maximize_value | |
| max_time_ms | No | ||
| max_cost_threshold | No | ||
| min_value_threshold | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so description carries full burden. It thoroughly explains the solver's behavior: handles dependencies, conflicts, multi-resource budgets, soft/hard constraints via penalty_per_unit_over, and returns a detailed response with status, costs, etc.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured with clear sections (intro, Args, Returns, Tips, Examples). Slightly verbose but every section adds value; could be trimmed slightly without losing clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity (8 parameters, nested structures, no output schema), the description covers all aspects: parameter details, return fields, multiple examples, and usage tips. Exceptional completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The 'Args' section adds significant meaning beyond the schema, explaining item structure, budgets, objective, thresholds, and solver time. Examples illustrate typical usage patterns.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool solves budget allocation/knapsack problems and distinguishes it from the sibling solve_constraint_model, stating 'Use this instead ... when you need to select items under budget constraints with dependencies and conflicts.'
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit guidance on when to use this tool (instead of solve_constraint_model) and gives tips for various applications (portfolio, features, campaigns) and objective choices (maximize_value vs maximize_count).
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
solve_constraint_modelA
Solve a general constraint or optimization model.
This tool solves discrete optimization and constraint satisfaction problems. It supports integer and boolean variables, linear constraints, global constraints (all_different, element, table), implications, and linear objectives.
Use cases include:
Project scheduling and resource allocation
Sudoku and logic puzzles
Configuration optimization
Tool/model selection under constraints
Routing and assignment problems
Budget allocation
Args: mode: Solver mode - 'satisfy' to find any feasible solution, 'optimize' to find the best solution according to the objective. variables: List of decision variables, each with: - id (str): Unique identifier - domain (dict): Domain specification with: - type (str): 'bool' or 'integer' - lower (int): Lower bound for integers (default 0) - upper (int): Upper bound for integers (default 1) - metadata (dict, optional): Context for explanations constraints: List of constraints, each with: - id (str): Unique identifier - kind (str): Constraint type - 'linear', 'all_different', 'element', 'table', or 'implication' - params (dict): Constraint-specific parameters: For 'linear': terms (list of {var, coef}), sense ('<=', '>=', '=='), rhs (number) For 'all_different': vars (list of variable ids) For 'element': index_var (str), array (list of int), target_var (str) For 'table': vars (list of str), allowed_tuples (list of lists) For 'implication': if_var (str), then (nested constraint dict) - metadata (dict, optional): Description and context objective: Optional objective function (required if mode='optimize'): - sense (str): 'min' or 'max' - terms (list): Linear terms as {var, coef} - metadata (dict, optional): Description search: Optional search configuration: - max_time_ms (int): Maximum solver time in milliseconds - max_solutions (int): Maximum solutions to return (default 1)
Returns: SolveConstraintModelResponse containing: - status: 'optimal', 'feasible', 'satisfied', 'infeasible', 'unbounded', 'timeout', or 'error' - objective_value: Objective value if applicable - solutions: List of solutions with variable assignments - explanation: Human-readable summary and binding constraints
Tips for LLMs: - Start with a small model to test; gradually add complexity. - For Sudoku: use 'all_different' constraints for rows, columns, and blocks. - For scheduling: use linear constraints for precedence and capacity. - Variable metadata is useful for building readable explanations. - Constraint metadata helps identify which constraints are tight. - If infeasible, check constraint metadata to diagnose conflicts. - Use 'satisfy' mode for puzzles; 'optimize' mode for cost/time minimization.
Example (simple knapsack):
python response = await solve_constraint_model( mode="optimize", variables=[ {"id": "take_item_1", "domain": {"type": "bool"}}, {"id": "take_item_2", "domain": {"type": "bool"}}, ], constraints=[ { "id": "capacity", "kind": "linear", "params": { "terms": [ {"var": "take_item_1", "coef": 3}, {"var": "take_item_2", "coef": 5}, ], "sense": "<=", "rhs": 7, }, } ], objective={ "sense": "max", "terms": [ {"var": "take_item_1", "coef": 10}, {"var": "take_item_2", "coef": 15}, ], }, )
| Name | Required | Description | Default |
|---|---|---|---|
| mode | Yes | ||
| search | No | ||
| objective | No | ||
| variables | Yes | ||
| constraints | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully discloses the tool's behavior: it supports discrete optimization with integer/bool variables, multiple constraint types, and linear objectives. It explains return statuses and provides tips for interpretation. It does not explicitly state whether the tool is read-only or has side effects, but the nature of solving implies no state mutation.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-organized with clear sections (intro, use cases, args, returns, tips, example). Every sentence adds value, no redundancy. Despite length, it is front-loaded with purpose and efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity (5 parameters, nested objects, no output schema), the description covers all input details, return fields, and provides practical tips. It is sufficient for an agent to use the tool correctly without external references.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, yet the description completely explains all parameters, including nested structures (variables, constraints, objective, search). Each constraint kind has detailed param specs, and an example illustrates usage. This fully compensates for the lack of schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states 'Solve a general constraint or optimization model' and lists diverse use cases (scheduling, puzzles, assignment, routing). This clearly differentiates it from sibling tools that target specific problems like scheduling or routing, establishing a clear general-purpose scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance on when to use 'satisfy' vs 'optimize' modes, tips for diagnosing infeasibility, and examples. However, it does not explicitly mention when to prefer sibling specialized tools (e.g., solve_scheduling_problem) over this general solver, leaving the decision to the agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
solve_routing_problemA
Solve vehicle routing problems (TSP/VRP) with optimal route planning.
Find optimal routes for vehicles visiting locations. Supports single-vehicle TSP, multi-vehicle VRP with capacity constraints, and multiple optimization objectives.
Args: locations: List of locations to visit, each with: - id: Unique identifier (required) - coordinates: (x, y) tuple for Euclidean distance (optional if distance_matrix provided) - demand: Load to pick up at this location (default 0) - service_time: Time spent at location in minutes (default 0) vehicles: List of vehicles (optional, defaults to single vehicle if omitted): - id: Vehicle identifier (required) - capacity: Maximum load capacity (default unlimited) - start_location: Starting location ID (required) - cost_per_distance: Cost per unit distance (default 1.0) - fixed_cost: Fixed cost if vehicle is used (default 0.0) distance_matrix: Optional distance matrix [i][j] = distance from location i to j. If omitted, uses Euclidean distance from coordinates. objective: Optimization goal (default "minimize_distance"): - "minimize_distance": Shortest total route length - "minimize_time": Shortest total time (distance + service times) - "minimize_cost": Lowest total cost (fixed + distance costs) - "minimize_vehicles": Use fewest vehicles possible max_time_ms: Solver time limit in milliseconds (default 60000)
Returns: SolveRoutingProblemResponse with: - status: OPTIMAL, FEASIBLE, or INFEASIBLE - routes: List of routes, each with vehicle_id, sequence of location IDs, total_distance, load_timeline - total_distance: Sum of all route distances - total_cost: Total cost across all routes - vehicles_used: Number of vehicles actually used - explanation: Human-readable summary
Tips for LLMs: - TSP (single vehicle): Omit vehicles parameter or provide one vehicle - VRP (multiple vehicles): Provide multiple vehicles with capacity limits - Capacity constraints: Set demand per location and capacity per vehicle - Use coordinates for geographic routing (automatically calculates distances) - Use distance_matrix when you have pre-computed distances or non-Euclidean metrics - minimize_vehicles: When you want to use as few vehicles as possible - minimize_cost: When vehicles have different costs (e.g., small truck vs large truck) - First location in route sequence is always the start location - Routes automatically return to start location (depot)
Example - Simple TSP: response = await solve_routing_problem( locations=[ {"id": "warehouse", "coordinates": (0, 0)}, {"id": "store_A", "coordinates": (10, 5)}, {"id": "store_B", "coordinates": (5, 10)}, ] ) # Single vehicle visits all locations, returns to warehouse
Example - Multi-Vehicle VRP: response = await solve_routing_problem( locations=[ {"id": "depot", "coordinates": (0, 0), "demand": 0}, {"id": "customer_1", "coordinates": (10, 5), "demand": 15}, {"id": "customer_2", "coordinates": (5, 10), "demand": 20}, {"id": "customer_3", "coordinates": (15, 15), "demand": 25}, ], vehicles=[ {"id": "truck_1", "capacity": 50, "start_location": "depot"}, {"id": "truck_2", "capacity": 40, "start_location": "depot"}, ], objective="minimize_distance" ) # Returns optimal routes respecting capacity limits
Example - Minimize Fleet Size: response = await solve_routing_problem( locations=[...], # 10 customers vehicles=[ {"id": "truck_1", "capacity": 100, "start_location": "depot"}, {"id": "truck_2", "capacity": 100, "start_location": "depot"}, {"id": "truck_3", "capacity": 100, "start_location": "depot"}, ], objective="minimize_vehicles" ) # Uses minimum number of trucks needed to serve all customers
| Name | Required | Description | Default |
|---|---|---|---|
| vehicles | No | ||
| locations | Yes | ||
| objective | No | minimize_distance | |
| max_time_ms | No | ||
| distance_matrix | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
With no annotations, the description fully discloses return values, status codes (OPTIMAL, FEASIBLE, INFEASIBLE), solver time limit, route structure, and behavior like returning to start. No negative side effects mentioned, which is appropriate for a solver tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is lengthy but well-structured with sections, bullet points, and examples. It is front-loaded with purpose and each section earns its place. Slightly verbose due to comprehensive examples, which is justified by the tool's complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (5 parameters, nested objects, no output schema), the description covers all input semantics, return values, and usage scenarios with examples. It is fully adequate for an agent to understand and invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0%, but the description provides detailed parameter documentation including types, defaults, and usage tips. It adds meaning beyond the schema, such as explaining the 'coordinates' tuple format and 'capacity' default unlimited.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states it solves vehicle routing problems (TSP/VRP) with optimal route planning. Distinguishes itself from siblings like solve_scheduling_problem by focusing on routing, not scheduling or assignment.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides explicit guidance on when to use TSP vs VRP, capacity constraints, distance_matrix vs coordinates, and different objective options. Includes tips and examples for common use cases, making it easy for the agent to choose correctly.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
solve_scheduling_problemA
Solve a task scheduling problem with dependencies and resource constraints.
This is a high-level interface for scheduling problems. Use this instead of solve_constraint_model when you have tasks with durations, dependencies, and resource constraints. The solver automatically builds the appropriate CP-SAT model.
Args: tasks: List of Task objects to schedule (id, duration required; dependencies, resources, etc. optional) resources: Optional list of Resource objects with capacity constraints objective: SchedulingObjective enum (MINIMIZE_MAKESPAN, MINIMIZE_COST, or MINIMIZE_LATENESS) max_time_ms: Maximum solver time in milliseconds (default 60000)
Returns: SolveSchedulingProblemResponse containing: - status: Solution status - makespan: Project completion time - schedule: List of task assignments with start/end times - resource_utilization: Resource usage summary - critical_path: Task IDs on critical path - solve_time_ms: Actual solve time - optimality_gap: Gap from best bound - explanation: Human-readable summary
Tips for LLMs: - Extract task durations from natural language (e.g., "takes 2 hours" -> duration: 2) - Parse dependencies carefully (e.g., "A before B" -> B depends on A) - Default resource capacity to system constraints if not specified - If user says "as fast as possible", use minimize_makespan - Check for circular dependencies before solving - If infeasible, check for conflicting deadlines or impossible dependencies
Example (simple project schedule):
python response = await solve_scheduling_problem( tasks=[ {"id": "build", "duration": 10, "dependencies": []}, {"id": "test", "duration": 5, "dependencies": ["build"]}, {"id": "deploy", "duration": 3, "dependencies": ["test"]} ], objective="minimize_makespan" ) # Returns optimal schedule with makespan = 18
Example (with resource constraints):
python response = await solve_scheduling_problem( tasks=[ {"id": "task_a", "duration": 5, "resources_required": {"cpu": 2}}, {"id": "task_b", "duration": 3, "resources_required": {"cpu": 3}}, ], resources=[{"id": "cpu", "capacity": 4}], objective="minimize_makespan" ) # Returns schedule respecting CPU capacity
| Name | Required | Description | Default |
|---|---|---|---|
| tasks | Yes | ||
| objective | No | minimize_makespan | |
| resources | No | ||
| max_time_ms | No |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, but the description fully explains behavior: automatically builds CP-SAT model, returns detailed response with status, makespan, schedule, resource utilization, critical path, solve time, optimality gap, and human-readable explanation. Warns about infeasibility and circular dependencies.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Description is fairly long but well-structured with sections for description, arguments, returns, tips, and examples. Every part adds value, but there is some redundancy (e.g., duplicate explanations in text and examples). Could be slightly more concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 4 parameters and no output schema, the description is comprehensive: explains input structure, returns, tips for LLMs, and includes two examples covering basic and resource-constrained scenarios. Covers error handling and edge cases like circular dependencies.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 0% per context, so description must compensate. The description does not add much to individual parameter definitions beyond the schema, but it provides extensive usage guidance and examples that show how to use parameters effectively. The tips section adds value for an AI agent.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it 'Solve a task scheduling problem with dependencies and resource constraints'. It distinguishes from sibling 'solve_constraint_model' by specifying this is for tasks with durations, dependencies, and resource constraints.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states 'Use this instead of solve_constraint_model when you have tasks with durations, dependencies, and resource constraints'. Provides tips for LLMs on extracting task information and checking for circular dependencies. Examples illustrate typical use cases.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
TDQS
Each tool targets a distinct optimization problem: assignment, budget/knapsack, general constraints, routing, and scheduling. Clear, non-overlapping purposes. No ambiguity.
All tool names follow the consistent pattern 'solve_<problem_type>', making them easily identifiable.
The server has 5 tools, covering the main classes of optimization problems. This is a well-scoped set that is neither too thin nor too heavy.
The tool surface covers major optimization domains (assignment, knapsack, routing, scheduling, general constraints). Minor gaps like network flow exist but are not critical given the general constraint solver.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Optimize crew and workforce schedules, resource allocation, and routing with linear and mixed-inte…
FinOps for Google Cloud: size 1- and 3-year CUD commitments to known demand. Also solves LP/MIP.
Deterministic reasoning stack for AI agents: simulate, decide & compute, plus cross-domain tools.
Cost-optimized LLM model routing recommendations for autonomous AI agents
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceMCP-ORTools integrates Google's OR-Tools constraint programming solver with Large Language Models through the MCP, enabling AI models to: Submit and validate constraint models Set model parameters Solve constraint satisfaction and optimization problems Retrieve and analyze solution21MIT
- AlicenseAqualityCmaintenanceEnables solving complex combinatorial optimization problems with logical and numerical constraints through multiple solvers (Z3, CVXPY, HiGHS, OR-Tools). Specializes in portfolio optimization, scheduling, resource allocation, and constraint satisfaction problems.55Apache 2.0
- AlicenseNot gradedqualityDmaintenanceEnables solving linear programming (LP) and mixed-integer linear programming (MILP) optimization problems through natural language, with built-in simplex and branch-and-cut solvers plus infeasibility diagnostics. Includes optional OR-Tools fallback for larger problems and supports parsing optimization problems from natural language descriptions.MIT
- AlicenseNot gradedqualityCmaintenanceProvides linear programming (LP), mixed-integer programming (MIP), and quadratic programming (QP) optimization capabilities using the HiGHS solver, enabling AI assistants to solve complex optimization problems like production planning, logistics, and portfolio optimization.2918MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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/IBM/chuk-mcp-solver'
If you have feedback or need assistance with the MCP directory API, please join our Discord server