Advanced optimization tools for Claude Code - 9 specialized solvers for production use
Version: 2.5.0 (All 4 Enhancements Complete) Status: Production Ready (9 Tools + 1 Orchestration Skill)
Want to try it immediately? Here's the fastest path:
git clone https://github.com/your-org/optimization-mcp
cd optimization-mcp
pip install -r requirements.txt# test_basic.py
from src.api.allocation import optimize_allocation
result = optimize_allocation(
objective={
"sense": "maximize",
"items": [
{"name": "project_a", "value": 100},
{"name": "project_b", "value": 150}
]
},
resources={"budget": {"total": 10000}},
item_requirements=[
{"name": "project_a", "budget": 6000},
{"name": "project_b", "budget": 5000}
]
)
print(f"Status: {result['status']}")
print(f"Optimal value: {result['objective_value']}")
print(f"Allocation: {result['allocation']}")Run: python test_basic.py
Expected output:
Status: optimal
Optimal value: 250.0
Allocation: {'project_a': 1, 'project_b': 1}
Add to ~/.claude.json:
{
"mcpServers": {
"optimization-mcp": {
"command": "python",
"args": ["/path/to/optimization-mcp/server.py"]
}
}
}Restart Claude Code, then try:
Claude, use optimization-mcp to allocate a $100K budget across 3 marketing channels
- Read full documentation below
- Try example workflows
- Explore all 9 tools
The Optimization MCP provides constraint-based optimization capabilities that integrate seamlessly with your existing Monte Carlo MCP. Find optimal resource allocations, robust solutions across scenarios, and make data-driven decisions under uncertainty.
- Deep MC Integration: Every tool has native Monte Carlo awareness - use percentile values, expected outcomes, or full scenario distributions
- Production Solvers: PuLP (LP/MILP), SciPy (nonlinear), CVXPY (quadratic), NetworkX (network flow)
- High Performance: NetworkX provides 10-100x speedup for logistics/routing problems (1K-10K variables)
- Zero-Friction Workflows: Optimization outputs feed directly into Monte Carlo validation tools
- Open Source: No commercial licenses required (Gurobi/CPLEX not needed)
- Production Ready: Internally tested, comprehensive error handling, helpful diagnostics
- Comprehensive Coverage: Network flow, Pareto frontiers, stochastic programming, column generation
Multi-objective optimization balancing conflicting goals (profit vs sustainability):
This visualization demonstrates how the Pareto frontier tool explores trade-offs between competing objectives, helping you make strategic decisions across multiple optimal solutions.
# Add marketplace
claude plugin marketplace add eesb99/optimization-mcp
# Install plugin
claude plugin install optimization-mcp
# Verify installation
/mcp
# Should show: ✔ optimization-mcp (connected, 9 tools)# Clone repository
git clone https://github.com/eesb99/optimization-mcp.git ~/.claude/mcp-servers/optimization-mcp
# Run setup
cd ~/.claude/mcp-servers/optimization-mcp
./setup.sh
# Add to ~/.claude.json
{
"mcpServers": {
"optimization-mcp": {
"command": "/Users/[username]/.claude/mcp-servers/optimization-mcp/run.sh"
}
}
}
# Restart Claude CodeAuto-Setup: The setup.sh script automatically creates a virtual environment and installs all dependencies.
This software is provided "as is" under the MIT License, without warranty of any kind, express or implied. The authors are not liable for any damages arising from the use of this software. Always validate optimization results before implementation.
Optimization results are mathematical models based on input data and assumptions. While algorithms are rigorously tested, real-world decisions require:
- Validation of results with domain experts
- Sensitivity analysis for critical parameters
- Testing with historical data before deployment
- Understanding of model limitations and assumptions
The portfolio optimization tool is for educational and analytical purposes only. It does not constitute financial, investment, or professional advice. Consult qualified financial advisors before making investment decisions. Past performance and model outputs do not guarantee future results.
All optimization tools undergo comprehensive internal testing and validation, but users should:
- Verify results independently for critical applications
- Test with known problems before production use
- Validate assumptions and input data quality
- Review solver status and warnings carefully
- Consider multiple scenarios and sensitivity analysis
Recommendation: Start with non-critical applications, validate thoroughly, then scale to production use.
Purpose: Resource allocation under constraints (budget, time, capacity)
Use Cases:
- Marketing budget across channels
- Production capacity across products
- Project selection with resource limits
- Ingredient formulation for beverages/foods
Example:
result = optimize_allocation(
objective={
"items": [
{"name": "google_ads", "value": 125000}, # Expected ROI
{"name": "linkedin", "value": 87000}
],
"sense": "maximize"
},
resources={
"budget": {"total": 100000}
},
item_requirements=[
{"name": "google_ads", "budget": 25000},
{"name": "linkedin", "budget": 18000}
]
)
# Output:
# {
# "status": "optimal",
# "objective_value": 212000.0,
# "allocation": {"google_ads": 1, "linkedin": 1, ...},
# "resource_usage": {...},
# "shadow_prices": {"budget": 1.25}, # Worth $1.25 per extra $1
# "monte_carlo_compatible": {...} # Ready for MC validation
# }Monte Carlo Integration:
# Use P50 (median) values from Monte Carlo simulation
result = optimize_allocation(
objective={...},
resources={...},
item_requirements=[...],
monte_carlo_integration={
"mode": "percentile",
"percentile": "p50",
"mc_output": mc_simulation_result
}
)Parameters:
objective: Dict withitems(list) andsense("maximize"/"minimize")resources: Dict of resource limits (e.g.,{"budget": {"total": 100000}})item_requirements: List of dicts with resource requirements per itemconstraints: Optional additional constraintsmonte_carlo_integration: Optional MC integration (3 modes: percentile, expected, scenarios)solver_options: Optional (time_limit,verbose)
Returns:
status: "optimal", "infeasible", "unbounded", or "error"objective_value: Optimal valueallocation: Dict of selected items (1 = selected, 0 = not)resource_usage: Utilization stats for each resourceshadow_prices: Marginal value of relaxing each constraintmonte_carlo_compatible: Output formatted for MC validation
NEW in v1.1.0: Optimize for multiple competing objectives with weighted scalarization.
Use Cases:
- Balance profit and sustainability
- Trade off return vs. risk
- Optimize cost and quality simultaneously
- Any multi-criteria decision problem
Example:
result = optimize_allocation(
objective={
"sense": "maximize",
"functions": [
{
"name": "profit",
"items": [
{"name": "product_a", "value": 100},
{"name": "product_b", "value": 150}
],
"weight": 0.7 # 70% weight on profit
},
{
"name": "sustainability",
"items": [
{"name": "product_a", "value": 80},
{"name": "product_b", "value": 60}
],
"weight": 0.3 # 30% weight on sustainability
}
]
},
resources={
"budget": {"total": 50000}
},
item_requirements=[
{"name": "product_a", "budget": 25000},
{"name": "product_b", "budget": 30000}
]
)
# Output includes objective breakdown:
# {
# "status": "optimal",
# "objective_value": 127.0, # 0.7*140 + 0.3*70
# "allocation": {"product_a": 1, "product_b": 0},
# "objective_breakdown": {
# "profit": {
# "value": 100,
# "weight": 0.7,
# "weighted_value": 70.0
# },
# "sustainability": {
# "value": 80,
# "weight": 0.3,
# "weighted_value": 24.0
# }
# }
# }Requirements:
- At least 2 objective functions required
- Weights must sum to 1.0 (within 0.01 tolerance)
- Each weight must be between 0 and 1
- Each function has its own
itemslist withnameandvalue
Backward Compatible: Single-objective format still works exactly as before.
NEW in v2.0.0: Advanced constraint types for complex decision logic.
Constraint Types:
1. Conditional (If-Then):
constraints=[
{
"type": "conditional",
"condition_item": "project_a",
"then_item": "project_b",
"description": "if_a_then_b"
}
]
# If project_a is selected, then project_b MUST be selected2. Disjunctive (OR - At Least N):
constraints=[
{
"type": "disjunctive",
"items": ["option_a", "option_b", "option_c"],
"min_selected": 2,
"description": "pick_at_least_2"
}
]
# At least 2 of the 3 options must be selected3. Mutual Exclusivity (Exactly N):
constraints=[
{
"type": "mutex",
"items": ["strategy_a", "strategy_b", "strategy_c"],
"exactly": 1,
"description": "pick_exactly_one"
}
]
# Exactly 1 strategy must be selected (XOR logic)Combined Example:
# Complex business logic: Pick one core product + conditionally required addons
result = optimize_allocation(
objective={...},
resources={...},
item_requirements=[...],
constraints=[
{"type": "mutex", "items": ["core_a", "core_b"], "exactly": 1},
{"type": "conditional", "condition_item": "core_a", "then_item": "addon_1"},
{"type": "disjunctive", "items": ["addon_1", "addon_2"], "min_selected": 1}
]
)Use Cases:
- Product bundling rules
- Technology dependency chains
- Strategic option selection
- Regulatory compliance constraints
Purpose: Find robust solutions that work well across Monte Carlo scenarios
Use Cases:
- Allocation that works in 85%+ of scenarios
- Worst-case optimization
- Risk-constrained decisions
Example:
# Step 1: Run Monte Carlo to generate scenarios
mc_result = run_business_scenario(
scenario_name="Product Launch",
revenue_assumptions={...},
cost_structure={...},
num_simulations=10000
)
# Step 2: Find robust allocation
result = optimize_robust(
objective={
"items": [{"name": "project_a"}, {"name": "project_b"}],
"sense": "maximize"
},
resources={"budget": {"total": 100000}},
item_requirements=[...],
monte_carlo_scenarios={
"scenarios": mc_result["scenarios"] # All 10K scenarios
},
robustness_criterion="best_average",
risk_tolerance=0.85 # Works in 85% of scenarios
)
# Output:
# {
# "allocation": {...},
# "robustness_metrics": {
# "expected_outcome": 125000,
# "worst_case_outcome": 95000,
# "scenarios_meeting_threshold": 0.92, # 92% of scenarios succeed
# "outcome_percentiles": {"p10": 98000, "p50": 125000, "p90": 152000}
# },
# "outcome_distribution": [...] # Outcome in each scenario
# }Parameters:
objective,resources,item_requirements: Same as optimize_allocationmonte_carlo_scenarios: Dict withscenarioslist from MC outputrobustness_criterion: "best_average", "worst_case", or "percentile"risk_tolerance: Float (0-1), e.g., 0.85 = works in 85% of scenariosconstraints,solver_options: Optional
Returns:
allocation: Robust allocation decisionrobustness_metrics: Performance statistics across scenariosoutcome_distribution: List of outcomes for validationmonte_carlo_compatible: Output for MC tools
NEW in v2.0.0: Portfolio optimization with risk-return tradeoffs using quadratic programming.
Purpose: Optimize investment portfolio allocation considering correlations and risk
Use Cases:
- Investment portfolio allocation
- Asset selection with risk-return tradeoffs
- Sharpe ratio maximization
- Efficient frontier construction
Optimization Objectives:
- Sharpe Ratio: Maximize (return - risk_free) / risk
- Min Variance: Minimize portfolio risk for target return
- Max Return: Maximize return for target risk
Example 1: Sharpe Ratio Optimization:
result = optimize_portfolio(
assets=[
{"name": "US_equity", "expected_return": 0.10},
{"name": "intl_equity", "expected_return": 0.09},
{"name": "bonds", "expected_return": 0.04}
],
covariance_matrix=[
[0.0225, 0.0100, 0.0020], # US equity: 15% std, correlations
[0.0100, 0.0256, 0.0015], # Intl equity: 16% std
[0.0020, 0.0015, 0.0036] # Bonds: 6% std
],
optimization_objective="sharpe",
risk_free_rate=0.025,
constraints={
"max_weight": 0.70, # Max 70% in any asset
"min_weight": 0.10 # Min 10% in each
}
)
# Output:
# {
# "status": "optimal",
# "weights": {"US_equity": 0.70, "intl_equity": 0.20, "bonds": 0.10},
# "expected_return": 0.092, # 9.2% expected return
# "portfolio_std": 0.1234, # 12.34% risk (std dev)
# "sharpe_ratio": 0.543, # (9.2% - 2.5%) / 12.34%
# "assets": [
# {
# "name": "US_equity",
# "weight": 0.70,
# "risk_contribution_pct": 165.1 # Contributes 165% of risk (due to correlations)
# },
# ...
# ]
# }Example 2: Minimum Variance:
# Find lowest-risk portfolio that achieves 6% return
result = optimize_portfolio(
assets=[...],
covariance_matrix=[...],
constraints={"target_return": 0.06},
optimization_objective="min_variance"
)
# Returns portfolio with minimum variance achieving 6% returnExample 3: Maximum Return:
# Find highest-return portfolio within risk budget
result = optimize_portfolio(
assets=[...],
covariance_matrix=[...],
constraints={"target_risk": 0.03}, # Max variance = 3%
optimization_objective="max_return"
)
# Returns portfolio with maximum return within risk limitParameters:
assets: List of{"name": str, "expected_return": float}covariance_matrix: N×N matrix of asset return covariancesoptimization_objective:"sharpe","min_variance", or"max_return"risk_free_rate: Risk-free rate for Sharpe (default: 0.02)constraints: Optional:max_weight: Max weight per asset (e.g., 0.30 = 30%)min_weight: Min weight per asset (e.g., 0.05 = 5%)target_return: Required formin_varianceobjectivetarget_risk: Required formax_returnobjectivelong_only: Prevent short selling (default: True)
monte_carlo_integration: Optional MC integrationsolver_options: Optional solver settings
Returns:
status: Optimization statusweights: Dict of optimal portfolio weights (sum to 1.0)expected_return: Portfolio expected returnportfolio_variance: Portfolio variance (risk²)portfolio_std: Portfolio standard deviation (risk)sharpe_ratio: (return - rf) / stdassets: Asset-level details with risk contributionsmonte_carlo_compatible: MC validation output
Solver: CVXPY with SCS (handles quadratic objectives and constraints)
NEW in v2.0.0: Task scheduling with dependencies and resource constraints.
Purpose: Optimize project schedules considering task dependencies, resource limits, and temporal constraints
Use Cases:
- Project scheduling (RCPSP)
- Job shop scheduling
- Task prioritization with deadlines
- Resource allocation over time
Optimization Objectives:
- Minimize Makespan: Complete project as fast as possible
- Maximize Value: Prioritize high-value tasks within time budget
Example 1: Software Project Schedule:
result = optimize_schedule(
tasks=[
{"name": "design", "duration": 5, "value": 100, "dependencies": [], "resources": {"developers": 2}},
{"name": "backend", "duration": 10, "value": 200, "dependencies": ["design"], "resources": {"developers": 3}},
{"name": "frontend", "duration": 8, "value": 150, "dependencies": ["design"], "resources": {"developers": 2}},
{"name": "testing", "duration": 4, "value": 80, "dependencies": ["backend", "frontend"], "resources": {"developers": 2}}
],
resources={"developers": {"total": 5}},
time_horizon=30,
optimization_objective="minimize_makespan"
)
# Output:
# {
# "status": "optimal",
# "makespan": 19, # Project finishes at time 19
# "schedule": {"design": 0, "backend": 5, "frontend": 5, "testing": 15},
# "critical_path": ["design", "backend", "testing"], # Tasks determining makespan
# "resource_usage": {...}, # Developer utilization over time
# "tasks": [
# {"name": "design", "start_time": 0, "end_time": 5, "on_critical_path": true},
# ...
# ]
# }Example 2: With Deadlines:
result = optimize_schedule(
tasks=[...],
resources={...},
time_horizon=30,
constraints=[
{"type": "deadline", "task": "testing", "time": 20}, # Must finish by time 20
{"type": "parallel_limit", "limit": 3} # Max 3 tasks in parallel
]
)Parameters:
tasks: List of tasks with:name: Task identifierduration: Time units requiredvalue: Task value/priority (optional, for maximize_value)dependencies: List of prerequisite task names (optional)resources: Resource requirements per time unit (optional)
resources: Available resources per time periodtime_horizon: Total scheduling windowconstraints: Optional temporal constraints:- Deadline: Task must finish by time T
- Release: Task cannot start before time T
- Parallel limit: Max N tasks simultaneously
optimization_objective:"minimize_makespan"or"maximize_value"monte_carlo_integration: Optional MC for uncertain durationssolver_options: Optional solver settings
Returns:
status: Optimization statusschedule: Dict mapping task → start_timemakespan: Project completion time (for minimize_makespan)total_value: Sum of scheduled task values (for maximize_value)resource_usage: Resource utilization timelinecritical_path: Task sequence determining makespantasks: Task-level details with critical path markersmonte_carlo_compatible: MC validation output
Solver: PuLP with CBC (MILP for task-time assignment)
NEW in v2.1.0: Custom optimization with automatic solver selection and flexible problem specification.
Purpose: Power user tool for rapid prototyping and custom optimization problems
Use Cases:
- Custom optimization formulations not fitting standard templates
- Rapid prototyping of new optimization problems
- When you know the mathematical form and want automatic solver selection
- Educational/research applications
Key Features:
- Auto-Solver Selection: Automatically detects and selects best solver (PuLP/SciPy/CVXPY)
- Flexible Specification: Dict-based problem definition
- All Solvers Accessible: Can override auto-detection to force specific solver
Example 1: Simple Knapsack Problem:
result = optimize_execute(
problem_definition={
"variables": [
{"name": "item1", "type": "binary"},
{"name": "item2", "type": "binary"},
{"name": "item3", "type": "binary"}
],
"objective": {
"coefficients": {"item1": 60, "item2": 100, "item3": 120},
"sense": "maximize"
},
"constraints": [
# Weight: 10*item1 + 20*item2 + 30*item3 <= 50
{"coefficients": {"item1": 10, "item2": 20, "item3": 30}, "type": "<=", "rhs": 50}
]
},
auto_detect=True
)
# Output:
# {
# "status": "optimal",
# "solver_used": "pulp", # Auto-detected for binary variables
# "objective_value": 220.0,
# "solution": {"item1": 0, "item2": 1, "item3": 1},
# "solve_time_seconds": 0.032,
# "problem_info": {"num_variables": 3, "num_constraints": 1}
# }Example 2: With Solver Override:
# Force CVXPY for continuous linear problem
result = optimize_execute(
problem_definition={
"variables": [
{"name": "x", "type": "continuous", "bounds": (0, 10)},
{"name": "y", "type": "continuous", "bounds": (0, 10)}
],
"objective": {
"coefficients": {"x": 3, "y": 4},
"sense": "maximize"
},
"constraints": [
{"coefficients": {"x": 1, "y": 2}, "type": "<=", "rhs": 10}
]
},
auto_detect=False,
solver_preference="cvxpy" # Override auto-detection
)Parameters:
problem_definition: Dict with:variables: List of{"name": str, "type": "continuous"|"integer"|"binary", "bounds": (lower, upper)}objective:{"coefficients": {var: coeff}, "sense": "maximize"|"minimize"}constraints: List of{"coefficients": {var: coeff}, "type": "<="|">="|"==", "rhs": number}
auto_detect: Auto-select best solver (default: True)solver_preference: Override with"pulp","scipy", or"cvxpy"monte_carlo_integration: Optional MC integrationsolver_options: Optional (time_limit,verbose)
Returns:
status: Optimization statussolver_used: Which solver was selectedobjective_value: Optimal valuesolution: Dict of variable valuessolve_time_seconds: Solve timeproblem_info: Problem statisticsshadow_pricesordual_values: Sensitivity information (solver-dependent)monte_carlo_compatible: MC validation output
Auto-Detection Logic:
- Has binary/integer variables → PuLP (CBC)
- Continuous linear → PuLP (default)
- Can override with
solver_preferenceparameter
When to Use:
- ✅ You have a custom problem not fitting standard templates
- ✅ You want to prototype quickly with dict specification
- ✅ You need access to all 3 solvers from one interface
- ✅ You're comfortable with mathematical formulation
When NOT to use:
- ❌ Standard allocation → Use optimize_allocation instead
- ❌ Portfolio → Use optimize_portfolio instead
- ❌ Scheduling → Use optimize_schedule instead
Solver: Auto-selected (PuLP/SciPy/CVXPY) or manual override
The Flexibility Layer: While specialized tools cover 90% of use cases, optimize_execute is deliberately designed for the other 10%.
When specialized tools fit (use these first):
- Budget allocation →
optimize_allocation - Portfolio →
optimize_portfolio - Scheduling →
optimize_schedule - Network routing →
optimize_network_flow - Multi-objective trade-offs →
optimize_pareto
When you need custom formulation (use optimize_execute):
- Custom knapsack variants
- Unusual constraint types
- Rapid prototyping of new problems
- Educational/research applications
- Any problem not fitting standard templates
Think of it as:
- Specialized tools = High-level API (easy, opinionated, 90% of cases)
- optimize_execute = Low-level API (flexible, general, 10% of cases)
Example - Custom Multi-Dimensional Knapsack:
# Specialized tools don't support this exact variant
# Use optimize_execute for full flexibility
result = optimize_execute(
problem_definition={
"variables": [
{"name": f"item_{i}", "type": "binary"}
for i in range(100)
],
"objective": {
"coefficients": {f"item_{i}": values[i] for i in range(100)},
"sense": "maximize"
},
"constraints": [
# Weight constraint
{"coefficients": {f"item_{i}": weights[i] for i in range(100)},
"type": "<=", "rhs": capacity},
# Volume constraint
{"coefficients": {f"item_{i}": volumes[i] for i in range(100)},
"type": "<=", "rhs": max_volume},
# Custom: At most 10 items from category A
{"coefficients": {f"item_{i}": 1 for i in category_a_items},
"type": "<=", "rhs": 10}
]
},
auto_detect=True
)You get:
- Auto-detection of solver (PuLP for this binary problem)
- All the power of mathematical programming
- None of the boilerplate of specialized tools
- Monte Carlo integration still available
Both have their place - use specialized tools when they fit (easier, better validation), optimize_execute when you need full control.
NEW in v2.2.0: Network flow optimization with specialized NetworkX algorithms for 10-100x speedup.
Purpose: Solve network flow problems (min-cost flow, max-flow, assignment)
Use Cases:
- Supply chain routing (warehouse → customer distribution)
- Transportation logistics (minimize shipping costs)
- Assignment problems (workers to tasks, machines to jobs)
- Maximum throughput/capacity problems
Key Features:
- High Performance: NetworkX specialized algorithms 10-100x faster than general LP
- Auto-Solver Selection: NetworkX for pure network flow, PuLP fallback for complex constraints
- Bottleneck Analysis: Identifies capacity-constrained edges
- Node Balance Tracking: Flow conservation verification at each node
Example 1: Supply Chain Min-Cost Flow:
result = optimize_network_flow(
network={
"nodes": [
{"id": "warehouse_A", "supply": 100},
{"id": "customer_1", "demand": 40},
{"id": "customer_2", "demand": 60}
],
"edges": [
{"from": "warehouse_A", "to": "customer_1", "capacity": 50, "cost": 5.0},
{"from": "warehouse_A", "to": "customer_2", "capacity": 80, "cost": 3.0}
]
},
flow_type="min_cost"
)
# Output:
# {
# "status": "optimal",
# "solver": "networkx",
# "total_cost": 380.0, # 40*5 + 60*3
# "flow_solution": {
# "flow_warehouse_A_customer_1": 40,
# "flow_warehouse_A_customer_2": 60
# },
# "bottlenecks": [{"edge": "...", "utilization": 1.0}],
# "node_balance": {...},
# "solve_time_seconds": 0.0001, # 1000x faster than LP!
# "monte_carlo_compatible": {...}
# }Example 2: Maximum Flow:
result = optimize_network_flow(
network={
"nodes": [
{"id": "source", "supply": 1000},
{"id": "intermediate", "demand": 0},
{"id": "sink", "demand": 1000}
],
"edges": [
{"from": "source", "to": "intermediate", "capacity": 50},
{"from": "intermediate", "to": "sink", "capacity": 100}
]
},
flow_type="max_flow"
)
# Finds maximum throughput (50 units, limited by first bottleneck)Example 3: Assignment Problem:
result = optimize_network_flow(
network={
"nodes": [
{"id": "worker_1", "supply": 1},
{"id": "worker_2", "supply": 1},
{"id": "task_A", "demand": 1},
{"id": "task_B", "demand": 1}
],
"edges": [
{"from": "worker_1", "to": "task_A", "cost": 10},
{"from": "worker_1", "to": "task_B", "cost": 15},
{"from": "worker_2", "to": "task_A", "cost": 12},
{"from": "worker_2", "to": "task_B", "cost": 8}
]
},
flow_type="assignment"
)
# Finds optimal one-to-one matching (worker_1→task_A, worker_2→task_B, cost=18)When to Use:
- ✅ Pure network flow problems (routing, logistics, assignment)
- ✅ Large-scale problems (1K-10K variables) where speed matters
- ✅ Supply chain optimization with transportation costs
- ✅ Capacity/throughput maximization
When NOT to use:
- ❌ Multi-commodity flow (different product types) → Use optimize_allocation
- ❌ Complex side constraints beyond flow conservation → optimize_execute with PuLP
Solver: NetworkX (primary) with PuLP fallback for complex cases Performance: <0.001s for 100 nodes, <2s for 1000 nodes
NEW in v2.3.0: Pareto multi-objective optimization - explore full trade-off frontier.
Purpose: Generate complete Pareto frontier showing all trade-offs between conflicting objectives
Use Cases:
- Strategic planning (profit vs sustainability vs risk)
- Design optimization (cost vs quality vs time)
- Product selection (revenue vs customer satisfaction)
- Multi-criteria decision support
Key Features:
- Full Frontier Generation: 20-100 non-dominated solutions (not just one weighted point)
- Knee Point Recommendation: Automatically identifies best balanced solution
- Trade-Off Analysis: Quantifies marginal rates of substitution between objectives
- Mixed Senses: Handles maximize + minimize objectives simultaneously
Example: Profit vs Sustainability Trade-Off:
result = optimize_pareto(
objectives=[
{
"name": "profit",
"items": [
{"name": "project_a", "value": 125000},
{"name": "project_b", "value": 87000}
],
"sense": "maximize"
},
{
"name": "sustainability",
"items": [
{"name": "project_a", "value": 65},
{"name": "project_b", "value": 92}
],
"sense": "maximize"
}
],
resources={"budget": {"total": 100000}},
item_requirements=[
{"name": "project_a", "budget": 60000},
{"name": "project_b", "budget": 45000}
],
num_points=20 # Generate 20 frontier points
)
# Output:
# {
# "status": "optimal",
# "pareto_frontier": [
# {
# "weights": {"profit": 1.0, "sustainability": 0.0},
# "allocation": {"project_a": 1, "project_b": 0},
# "objective_values": {"profit": 125000, "sustainability": 65}
# },
# ... 18 more points ...
# {
# "weights": {"profit": 0.0, "sustainability": 1.0},
# "allocation": {"project_a": 0, "project_b": 1},
# "objective_values": {"profit": 87000, "sustainability": 92}
# }
# ],
# "num_frontier_points": 20,
# "recommended_point": {...}, # Knee point (best balance)
# "tradeoff_analysis": {
# "objective_ranges": {...},
# "tradeoff_rates": {"sustainability_per_profit": {...}}
# }
# }When to Use:
- ✅ Don't know the "right" trade-off weights upfront
- ✅ Need to show executives/stakeholders multiple options
- ✅ Want to understand sensitivity to objective priorities
- ✅ Multi-criteria decision problems
When NOT to use:
- ❌ Already know exact weights → Use optimize_allocation with multi-objective
- ❌ Single objective → Use optimize_allocation
Solver: PuLP (solves weighted sums systematically) Performance: ~0.5-2s for 20 frontier points
Understanding the performance characteristics of each tool helps you choose the right approach and set realistic expectations.
Recommended limits:
- Items: <500 (optimal performance)
- Resources: <100
- Binary/integer variables: <1000
- Constraints: <1000
Performance characteristics:
- Uses PuLP with CBC solver (branch-and-cut MIP)
- Small problems (<50 items): <1 second
- Medium problems (50-500 items): <10 seconds
- Large problems (500-1000 items): <60 seconds
When to use: Budget allocation, resource assignment, selection problems
Recommended limits:
- Items: <100 (candidate generation is combinatorial)
- Scenarios: <1000
- Total evaluations (items × scenarios): <100,000
Performance characteristics:
- Generates candidate allocations, evaluates across scenarios
- Evaluation time grows linearly with scenarios
- Candidate generation can be exponential in items
When to use: Risk-aware allocation under uncertainty
Recommended limits:
- Assets: <500
- Covariance matrix: N×N must fit in memory (~500×500 = 2MB)
Performance characteristics:
- Uses CVXPY with SCS/OSQP solvers (quadratic programming)
- Small portfolios (<50 assets): <1 second
- Medium portfolios (50-200 assets): <5 seconds
- Large portfolios (200-500 assets): <30 seconds
When to use: Investment portfolio optimization, risk-return trade-offs
Recommended limits:
- Tasks: <50
- Time horizon: <100 periods
- Total time-indexed variables (tasks × horizon): <5000
Performance characteristics:
- Uses time-indexed formulation (binary variable per task-time pair)
- Variables = tasks × time_horizon
- Small projects (<20 tasks): <10 seconds
- Medium projects (20-50 tasks): <60 seconds
When to use: Project scheduling, resource-constrained planning
Recommended limits:
- Nodes: <10,000
- Edges: <100,000
Performance characteristics:
- Uses NetworkX specialized algorithms (network simplex, Edmonds-Karp)
- Exploits network structure for 100-5000x speedup vs general LP
- Small networks (<100 nodes): <0.1 seconds
- Medium networks (100-1000 nodes): <1 second
- Large networks (1000-10000 nodes): <10 seconds
When to use: Transportation, logistics, routing, assignment problems
Recommended limits:
- Frontier points: 20-100 (more points = finer trade-off curve)
- Items: Same as optimize_allocation
- Objectives: 2-4 (visualization becomes difficult beyond 3)
Performance characteristics:
- Solves one optimization per frontier point
- Total time ≈ single optimization × number of points
- 20 points typically takes 10-30 seconds
When to use: Multi-objective trade-off analysis, exploring decision space
Recommended limits:
- Scenarios: <200 (extensive form size scales linearly)
- First-stage variables: <500
- Second-stage variables: <500
- Total problem size: n₁ + S×n₂ < 100,000
Performance characteristics:
- Uses 2-stage extensive form (single large LP)
- Problem size = first_stage + scenarios × second_stage
- 50 scenarios, 100 vars/stage: ~5 seconds
- 200 scenarios, 200 vars/stage: ~60 seconds
When to use: Sequential decisions with uncertainty revelation (inventory, capacity planning)
Recommended limits:
- Master problem variables: <10,000 (framework ready, user implements pricing)
- Iterations: <100
Performance characteristics:
- Framework for large-scale problems (>1000 variables)
- Performance depends on user-provided pricing subproblem
- Currently returns with initial columns (placeholder pricing)
When to use: Very large problems, cutting stock, crew scheduling (requires custom pricing)
Recommended limits:
- Variables: Depends on auto-detected solver
- PuLP (LP/MIP): <10,000 variables
- SciPy (nonlinear): <1,000 variables
- CVXPY (QP): <5,000 variables
Performance characteristics:
- Auto-detects problem type and selects appropriate solver
- Performance matches selected backend solver
When to use: Custom problems not covered by specialized tools
- Start small: Test with 10-20% of full problem size first
- Use network_flow for network problems: 100-5000x faster than general LP
- Reduce scenarios: 50 scenarios often sufficient for stochastic problems
- Use robust over stochastic for simple cases: Faster evaluation, no extensive form
- Pareto frontier: 20 points usually sufficient to see trade-off curve
- Check solver_options: Set
time_limitto prevent runaway solves
If your problem exceeds recommended limits:
- Decomposition: Break into smaller subproblems
- Aggregation: Group similar items/resources
- Sampling: Use subset of scenarios for stochastic
- Heuristics: Use optimize_robust with candidate sampling
- Column generation: Use optimize_column_gen for very large problems
- Commercial solvers: Consider Gurobi/CPLEX for 10x+ speedup (not included)
This MCP has deep Monte Carlo integration - every tool can work with uncertainty. However, tools use different patterns based on their needs.
| Tool | MC Parameter | Modes Supported | Purpose |
|---|---|---|---|
| optimize_allocation | monte_carlo_integration | percentile, expected | Use MC values in objective |
| optimize_robust | monte_carlo_scenarios | scenarios only | Evaluate across all scenarios |
| optimize_portfolio | monte_carlo_integration | percentile, expected | Use MC returns/covariance |
| optimize_schedule | monte_carlo_integration | percentile, expected | Use MC durations |
| optimize_execute | monte_carlo_integration | percentile, expected | Use MC coefficients |
| optimize_network_flow | monte_carlo_integration | percentile, expected | Use MC costs/capacities |
| optimize_pareto | monte_carlo_integration | percentile, expected | Use MC objective values |
| optimize_stochastic | scenarios | scenarios only | Model uncertainty explicitly |
Used by: allocation, portfolio, schedule, execute, network_flow, pareto
Purpose: Extract specific values (P10/P50/P90 or expected) from MC output and use in optimization
Example:
# Step 1: Generate MC scenarios
mc_result = run_business_scenario(
scenario_name="Revenue Forecast",
assumptions={...},
num_simulations=10000
)
# Step 2: Use P50 (median) values in optimization
result = optimize_allocation(
objective={...},
resources={...},
item_requirements=[...],
monte_carlo_integration={
"mode": "percentile", # or "expected"
"percentile": "p50", # p10, p50, or p90
"mc_output": mc_result # Full MC output
}
)Modes:
"percentile": Use P10/P50/P90 values from distribution- P10 = Conservative (pessimistic)
- P50 = Base case (median)
- P90 = Optimistic
"expected": Use mean values from distribution
What happens: Tool extracts specified percentile/expected values from mc_output and uses them in optimization
Used by: optimize_robust, optimize_stochastic
Purpose: Evaluate decisions across ALL scenarios (not just one percentile)
Example for optimize_robust:
# Step 1: Generate MC scenarios
mc_result = run_business_scenario(
scenario_name="Product Launch",
assumptions={...},
num_simulations=10000
)
# Step 2: Find robust allocation
result = optimize_robust(
objective={...},
resources={...},
item_requirements=[...],
monte_carlo_scenarios={
"scenarios": mc_result["scenarios"] # Pass ALL scenarios
},
robustness_criterion="best_average",
risk_tolerance=0.85 # Works in 85% of scenarios
)Example for optimize_stochastic:
result = optimize_stochastic(
first_stage={...},
second_stage={...},
scenarios=[ # Explicit scenario list
{"probability": 0.2, "demand": 100, "price": 50},
{"probability": 0.5, "demand": 150, "price": 45},
{"probability": 0.3, "demand": 200, "price": 40}
]
)What happens: Tool evaluates optimization across all scenarios
optimize_robust: Tests candidate allocations against all scenariosoptimize_stochastic: Models uncertainty explicitly in 2-stage formulation
Use Pattern A (percentile/expected) when:
- You want a single deterministic optimization
- You're comfortable picking P10/P50/P90 upfront
- You want fast solve times
- Example: "Allocate budget using median ROI values"
Use Pattern B (scenarios) when:
- You want robustness across uncertainty
- You care about worst-case or risk tolerance
- You need sequential decisions with uncertainty revelation
- Example: "Find allocation that works in 85% of scenarios"
Workflow 1: Conservative Planning
# Use P10 (pessimistic) for conservative allocation
result = optimize_allocation(
...,
monte_carlo_integration={
"mode": "percentile",
"percentile": "p10",
"mc_output": mc_result
}
)Workflow 2: Robust Optimization
# First try base case (P50)
base = optimize_allocation(..., percentile="p50")
# Then test robustness across all scenarios
robust = optimize_robust(
...,
monte_carlo_scenarios={"scenarios": mc_result["scenarios"]}
)
# Compare: Does base case work in 85%+ scenarios?Workflow 3: Stochastic Sequential Decisions
# Inventory planning: Order now, adjust later based on demand
result = optimize_stochastic(
first_stage={ # Order decision (now)
"variables": [...],
"objective": {...}
},
second_stage={ # Adjustment decision (after seeing demand)
"variables": [...],
"objective": {...}
},
scenarios=[...] # Possible demand scenarios
)If you're using the old pattern and want to update:
Old (still works):
optimize_allocation(objective={...}, resources={...}, item_requirements=[...])New (with MC):
optimize_allocation(
objective={...},
resources={...},
item_requirements=[...],
monte_carlo_integration={
"mode": "percentile",
"percentile": "p50",
"mc_output": mc_result
}
)Backward compatible: All tools work without MC parameters (deterministic mode)
Common data structures used across multiple tools. Learn once, use everywhere.
Used in: optimize_allocation, optimize_schedule, optimize_pareto, optimize_stochastic, optimize_robust
Format:
{
"resource_name": {
"total": number, # Required: Total available amount
"unit": string # Optional: Unit of measurement
}
}Examples:
# Simple budget
resources = {"budget": {"total": 100000}}
# Multiple resources with units
resources = {
"budget": {"total": 100000, "unit": "USD"},
"time": {"total": 40, "unit": "hours"},
"capacity": {"total": 500, "unit": "units"}
}Used in: optimize_allocation, optimize_robust, optimize_pareto
Format:
[
{
"name": string, # Required: Unique item identifier
"resource1": number, # Required: Amount of resource1 needed
"resource2": number, # Optional: Amount of resource2 needed
...
}
]Examples:
# Budget-only requirements
item_requirements = [
{"name": "campaign_a", "budget": 25000},
{"name": "campaign_b", "budget": 18000}
]
# Multi-resource requirements
item_requirements = [
{
"name": "project_a",
"budget": 60000,
"time": 20,
"capacity": 100
},
{
"name": "project_b",
"budget": 45000,
"time": 15,
"capacity": 75
}
]Important: Resource names in requirements must match resource names in resources dict
Used in: optimize_allocation, optimize_robust, optimize_pareto
Single Objective Format:
{
"sense": "maximize" | "minimize",
"items": [
{
"name": string, # Must match name in item_requirements
"value": number # Objective coefficient
}
]
}Multi-Objective Format (allocation only):
{
"sense": "maximize" | "minimize",
"functions": [
{
"name": string, # Function name (e.g., "profit")
"weight": number, # Weight (0-1, must sum to 1.0)
"items": [
{"name": string, "value": number}
]
}
]
}Example:
# Single objective
objective = {
"sense": "maximize",
"items": [
{"name": "product_a", "value": 100},
{"name": "product_b", "value": 150}
]
}
# Multi-objective (profit vs sustainability)
objective = {
"sense": "maximize",
"functions": [
{
"name": "profit",
"weight": 0.7,
"items": [
{"name": "product_a", "value": 100},
{"name": "product_b", "value": 150}
]
},
{
"name": "sustainability",
"weight": 0.3,
"items": [
{"name": "product_a", "value": 80},
{"name": "product_b", "value": 60}
]
}
]
}Used in: optimize_allocation, optimize_schedule
Format:
[
{
"type": "min" | "max" | "conditional" | "disjunctive" | "mutex",
"items": [string], # Item names
"limit": number, # For min/max
"min_selected": number, # For disjunctive
"exactly": number, # For mutex
"condition_item": string, # For conditional
"then_item": string, # For conditional
"description": string # Optional: Human-readable
}
]Examples:
# Minimum selection (at least 1 core product)
{"type": "min", "items": ["core_a", "core_b"], "limit": 1}
# If-then logic (if A then must have B)
{"type": "conditional", "condition_item": "project_a", "then_item": "project_b"}
# Pick at least N (at least 2 of 3 options)
{"type": "disjunctive", "items": ["opt1", "opt2", "opt3"], "min_selected": 2}
# Pick exactly N (exactly 1 strategy - XOR)
{"type": "mutex", "items": ["strategy_a", "strategy_b"], "exactly": 1}
# Combined (complex business logic)
constraints = [
{"type": "mutex", "items": ["core_a", "core_b"], "exactly": 1},
{"type": "conditional", "condition_item": "core_a", "then_item": "addon_1"},
{"type": "disjunctive", "items": ["addon_1", "addon_2"], "min_selected": 1}
]Used in: optimize_network_flow
Format:
{
"nodes": [
{
"id": string, # Unique node identifier
"supply": number, # Positive = source (optional)
"demand": number # Positive = sink (optional)
}
],
"edges": [
{
"from": string, # Source node id
"to": string, # Target node id
"capacity": number, # Max flow on edge (optional)
"cost": number # Cost per unit flow (optional)
}
]
}Example:
network = {
"nodes": [
{"id": "warehouse", "supply": 100},
{"id": "customer_1", "demand": 40},
{"id": "customer_2", "demand": 60}
],
"edges": [
{"from": "warehouse", "to": "customer_1", "capacity": 50, "cost": 5.0},
{"from": "warehouse", "to": "customer_2", "capacity": 80, "cost": 3.0}
]
}Node types:
- Source:
supply > 0(produces flow) - Sink:
demand > 0(consumes flow) - Transshipment: Neither supply nor demand (passes flow through)
Used in: All tools
Format:
{
"time_limit": number, # Optional: Max solve time (seconds)
"verbose": boolean # Optional: Enable debug output
}Example:
solver_options = {
"time_limit": 30, # Stop after 30 seconds
"verbose": True # Print solver progress
}Usage:
result = optimize_allocation(
objective={...},
resources={...},
item_requirements=[...],
solver_options={"time_limit": 60, "verbose": False}
)Find optimal allocation, validate with Monte Carlo, test assumption robustness.
User: "Allocate $100K marketing budget with uncertain ROI"
Step 1: Optimize allocation
result = optimize_allocation(
objective={...},
resources={"budget": {"total": 100000}},
item_requirements=[...]
)
Step 2: Validate confidence (uses MC-compatible output)
confidence = validate_reasoning_confidence(
decision_context="Q1 marketing allocation",
assumptions=result["monte_carlo_compatible"]["assumptions"],
success_criteria=result["monte_carlo_compatible"]["recommended_params"]["success_criteria"]
)
# Returns: 87% chance of achieving >90% of optimal value
Step 3: Test robustness
robustness = test_assumption_robustness(
base_answer=f"Allocate {result['allocation']}",
critical_assumptions=result["monte_carlo_compatible"]["assumptions"],
stress_test_ranges={...}
)
# Returns: Breaks if Google Ads ROI < $35K (currently $50K)
Result: Optimal allocation + 87% confidence + breaking points identified
Generate scenarios with Monte Carlo, optimize for robustness.
User: "Find allocation that works in 85% of scenarios"
Step 1: Generate MC scenarios
mc = run_business_scenario(
scenario_name="Product Launch",
revenue_assumptions={...},
num_simulations=10000
)
Step 2: Robust optimization
opt = optimize_robust(
objective={...},
monte_carlo_scenarios={"scenarios": mc["scenarios"]},
risk_tolerance=0.85
)
Step 3: Sensitivity analysis
sensitivity = run_sensitivity_analysis(
variables_to_test=["revenue", "cost"],
outcome_data=opt["outcome_distribution"]
)
Result: Robust allocation + sensitivity tornado diagram
| Solver | Type | Best For | Scale |
|---|---|---|---|
| PuLP + CBC | LP/MILP | Resource allocation, scheduling, formulation | Up to 10,000 vars |
| SciPy | Nonlinear | Continuous optimization with bounds/constraints | 10-1000 vars |
optimization-mcp/
├── server.py # MCP entry point
├── src/
│ ├── api/ # Tool implementations
│ │ ├── allocation.py # optimize_allocation
│ │ └── robust.py # optimize_robust
│ ├── solvers/ # Solver wrappers
│ │ ├── base_solver.py # Abstract base class
│ │ ├── pulp_solver.py # PuLP wrapper
│ │ └── scipy_solver.py # SciPy wrapper
│ ├── integration/ # MC integration
│ │ ├── monte_carlo.py # MC integration layer
│ │ └── data_converters.py # Data validation
│ └── utils/ # Utilities
| Problem Size | Target Time | Use Case |
|---|---|---|
| Small (< 50 vars) | < 1 sec | Formulation problems |
| Medium (50-500 vars) | < 10 sec | Resource allocation |
| Large (500-1000 vars) | < 60 sec | Complex scheduling |
-
Check configuration:
grep -A5 '"optimization-mcp"' ~/.claude/config/mcp-profiles.json
-
Verify server.py is executable:
ls -l ~/.claude/mcp-servers/optimization-mcp/server.py -
Check logs:
tail -f /tmp/optimization-mcp.log
If you get status: "infeasible":
- Check that at least one item fits within resource limits
- Verify constraints aren't contradictory
- Use smaller problem to debug
If optimization takes > 60 seconds:
- Reduce problem size (fewer items/constraints)
- Add
solver_options: {"time_limit": 30}to stop early - Consider breaking into subproblems
- Tool 3:
optimize_portfolio- Portfolio optimization with Sharpe ratio - Tool 4:
optimize_schedule- Task scheduling with dependencies - CVXPY integration for quadratic objectives
- Tool 5:
optimize_execute- Custom workflows with code execution - Orchestration skill:
robust-optimization- End-to-end automation - Performance benchmarks and optimization
Problem: Allocate $100K across 5 channels with uncertain conversion rates
# Generate MC scenarios for conversion uncertainty
mc_result = run_business_scenario(
scenario_name="Marketing ROI",
revenue_assumptions={
"seo_conversion": {"distribution": "normal", "params": {"mean": 0.04, "std": 0.01}},
"content_conversion": {"distribution": "normal", "params": {"mean": 0.03, "std": 0.008}},
# ... other channels
},
num_simulations=10000
)
# Optimize using P50 (median) values
opt_result = optimize_allocation(
objective={
"items": [
{"name": "seo", "value": "from_mc"},
{"name": "content", "value": "from_mc"},
# ... other channels
],
"sense": "maximize"
},
resources={"budget": {"total": 100000}},
item_requirements=[
{"name": "seo", "budget": 25000},
{"name": "content", "budget": 18000},
# ... other channels
],
monte_carlo_integration={
"mode": "percentile",
"percentile": "p50",
"mc_output": mc_result
}
)
# Validate robustness
robustness = test_assumption_robustness(
base_answer=f"Allocate {opt_result['allocation']}",
critical_assumptions=opt_result["monte_carlo_compatible"]["assumptions"],
stress_test_ranges={
"seo_conversion": {"low": 0.01, "high": 0.07}
}
)
Result:
- Optimal: SEO 40%, Content 30%, Paid 20%, Email 8%, Events 2%
- Expected ROI: 2.5x
- Confidence: 87% chance of >2.0x ROI
- Risk: Breaks if SEO conversion < 2% (currently 4%)
- mcp >= 0.9.0 - Model Context Protocol
- pulp >= 2.7.0 - Linear/integer programming
- scipy >= 1.16.0 - Scientific computing
- numpy >= 2.3.0 - Numerical arrays
- pytest >= 7.0.0 - Testing framework
Part of Claude Code MCP ecosystem. Use responsibly.
- Issues: Report problems in your Claude Code setup
- Documentation: See plan file at
~/.claude/plans/resilient-frolicking-wreath.md - Examples: Check
examples/directory for complete workflows
Week 1 Status: ✓ Production Ready with 2 Core Tools
Next: Week 2 - Portfolio optimization and scheduling tools
