Skip to main content

MiniZinc MCP Server

MiniZinc MCP Server logo

M8ven Score

An MCP server that exposes MiniZinc constraint solving and optimization to LLM clients such as opencode, Claude Desktop, and Cursor. It lets an agent parse, type-check, and solve MiniZinc models directly from a chat session.

Built with the MCP Python SDK v2 and the MiniZinc Python binding.


Demo

MiniZinc MCP Server Demo

Install it

1. Prerequisites

Only two things need to be installed, once per machine:

  • uv — curl -LsSf https://astral.sh/uv/install.sh | sh
  • MiniZinc 2.6+ with the minizinc executable on PATH (includes a default solver, Gecode)

Everything else is fetched automatically by uv — there is no clone, no venv setup, and no manual pip install on your side.

2. Install the server (pick one)

Install the latest released version globally (best if you use it in several projects):

uv tool install minizinc-mcp

Or run the latest released version on demand, with nothing installed:

uvx minizinc-mcp

From GitHub (latest development version)

To run the latest development version directly from the repository, use:

uvx --from git+https://github.com/carban/minizinc-mcp minizinc-mcp

To install that development version globally instead:

uv tool install --from git+https://github.com/carban/minizinc-mcp minizinc-mcp

The GitHub installation tracks the repository's main branch; PyPI provides released versions.

3. Wire it into your MCP client

The server runs over stdio. Tell your MCP client to launch it:

opencode — project level (add this to opencode.jsonc in your project):

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "minizinc": {
      "type": "local",
      "command": ["uvx", "minizinc-mcp"]
    }
  }
}

opencode — global (add the same mcp.minizinc block to ~/.config/opencode/opencode.json):

{
  "mcp": {
    "minizinc": {
      "type": "local",
      "command": ["uvx", "minizinc-mcp"]
    }
  }
}

Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "minizinc": {
      "command": "uvx",
      "args": ["minizinc-mcp"]
    }
  }
}

If you are using the GitHub installation instead, replace ["uvx", "minizinc-mcp"] in the opencode configuration with ["uvx", "--from", "git+https://github.com/carban/minizinc-mcp", "minizinc-mcp"], and replace the Claude Desktop arguments with ["--from", "git+https://github.com/carban/minizinc-mcp", "minizinc-mcp"].

4. Verify it works

Restart your client. Eight tools should now be available, prefixed with minizinc_:

  • minizinc_list_tools
  • minizinc_list_solvers
  • minizinc_validate_model
  • minizinc_solve_model
  • minizinc_compare_solvers
  • minizinc_solve_model_by_path
  • minizinc_get_model_info
  • minizinc_get_flatzinc

Quick sanity check — ask your client: "list the available MiniZinc solvers". You should see gecode, chuffed, highs, and anything else installed on the machine.


Using the MiniZinc skill with opencode

The skills/minizinc/ folder contains an opencode skill that steers an agent through constraint programming, combinatorial, and optimization work: modeling problems with MiniZinc, type-checking models, running or comparing solvers, and rendering results as Markdown tables (instead of raw JSON).

The skill lives in a top-level skills/ folder so it is visible in the repo, but opencode does not auto-discover it from there — you must install it first.

1. Prerequisite

Register the MCP server as shown in the Wire it into your MCP client section above.

2. Install the skill (pick one)

Copy it into a project where you want it active (auto-discovered by opencode, no config needed):

cp -r skills/minizinc <your-project>/.opencode/skills/

Or install it globally so it is available in every project:

cp -r skills/minizinc ~/.config/opencode/skills/

Or point opencode at this repo's skills/ folder (scanned recursively for SKILL.md) by adding to opencode.json:

{
  "$schema": "https://opencode.ai/config.json",
  "skills": {
    "paths": ["/path/to/minizinc-mcp/skills"]
  }
}

Claude Code users can copy the folder to ~/.claude/skills/minizinc/ instead of ~/.config/opencode/skills/.

3. Use it

Restart your client, then simply describe a problem. For example:

  • "Solve this knapsack as a MiniZinc model."
  • "Optimize a production schedule with MiniZinc."
  • "Compare the available solvers on this model and recommend one."
  • "Write a MiniZinc model for this timetabling problem and check it."

The skill activates automatically and drives the minizinc_* tools — modeling, validating, solving, comparing solvers, and presenting results as tables.


What it does

Tool Description
list_tools Lists the names of all tools exposed by this MiniZinc MCP server, including list_tools itself.
list_solvers Lists every MiniZinc solver installed on the machine. The returned tag names (e.g. gecode, chuffed, highs) can be passed to solve_model.
validate_model Parses and type-checks MiniZinc model code without solving it. Useful for checking model syntax up front. Returns VALID or INVALID with an error message.
solve_model Solves a MiniZinc model given as source code: once, exhaustively (all_solutions), or with a solution / time limit. Returns the status, solution(s), objective value (for optimization problems), and solver statistics.
compare_solvers Solves the same model once with each requested solver and returns the individual solve_model results keyed by solver name. Use this for solver comparisons and performance evaluation.
solve_model_by_path Same as solve_model but loads the model and its optional data (.dzn) file from paths instead of source code.
get_model_info Inspects a model without solving it: returns its solve method (satisfy/minimize/maximize) and the declared input parameters and output variables with their types. Useful for an agent to know exactly which params a model expects.
get_flatzinc Compiles a model (and optional data) to FlatZinc text without solving it. Returns the .fzn model, the .ozn output model, and flattening statistics. Useful for debugging and low-level inspection.

solve_model arguments

Argument Type Default Description
model_code str (required) The MiniZinc source code (.mzn) of the model.
params dict | str None Parameter assignments like a .dzn file: a JSON object mapping names to values (a JSON string encoding such an object is also accepted).
solver str "gecode" Which solver to use (see list_solvers).
all_solutions bool False Compute all solutions of a solve satisfy problem.
max_solutions int | None None Stop after at most this many solutions.
timeout_seconds int | None None Solver time limit in seconds.

compare_solvers arguments

Argument Type Default Description
model_code str (required) The same MiniZinc source model to pass to every solver.
solvers list[str] (required) Solver tag names to run, normally from list_solvers.
params dict | None None The same parameter assignments to pass to every solver.
all_solutions bool False Compute all solutions of a solve satisfy problem with every solver.
max_solutions int | None None Stop each solver after finding at most this many solutions.
timeout_seconds int | None None Per-solver time limit in seconds.

compare_solvers calls solve_model once per requested solver and returns each result under results, keyed by solver name. A solver error is retained in that solver's result without stopping the remaining runs. The shape is:

{
  "results": {
    "gecode": {
      "status": "OPTIMAL_SOLUTION",
      "objective": 1700,
      "statistics": { "time": 0.01, "nodes": 12 }
    },
    "chuffed": {
      "status": "OPTIMAL_SOLUTION",
      "objective": 1700,
      "statistics": { "time": 0.02, "nodes": 8 }
    }
  }
}

The solve_model result is a JSON object like:

{
  "status": "OPTIMAL_SOLUTION",
  "objective": 9,
  "solution": { "objective": 9, "x": 9, "y": 1 },
  "statistics": { "time": 0.204, "nodes": 3, ... }
}

status is one of SATISFIED, OPTIMAL_SOLUTION, ALL_SOLUTIONS, UNSATISFIABLE, UNKNOWN, or ERROR. validate_model, solve_model, and each individual compare_solvers run never raise in normal operation — errors are returned inside the result dict.

The tool descriptions also instruct the client agent to present solving results, solver comparisons, and model info to you as Markdown tables instead of raw JSON, so solve_model and compare_solvers answers read like tables even though the tools themselves always return structured JSON.


Developing locally

Clone the repo, then:

uv sync          # create the environment and install mcp + minizinc

The server speaks the MCP stdio transport, so it is launched as a subprocess by an MCP client. Run it with the SDK inspector:

uv run mcp dev server.py

that opens the MCP Inspector in the browser where every tool can be called interactively. A minimal programmatic smoke test:

uv run python -c "
import asyncio
from mcp import Client
from mcp.client.stdio import StdioServerParameters

async def main():
    params = StdioServerParameters(command='uv', args=['run', 'python', 'server.py'], cwd='.')
    async with Client(params) as client:
        result = await client.call_tool('solve_model', {
            'model_code': 'var 1..10: x; var 1..10: y; constraint x + y = 10; solve maximize x;'
        })
        print(result.content[0].text)

asyncio.run(main())
"

Running the tests

Install the test dependencies, then run the suite:

uv sync --group dev
uv run pytest -q

The tests in tests/ launch the server end-to-end over stdio and call every tool through the MCP protocol, solving the example model in example/. They need a working MiniZinc install (the same prerequisite as for developers).

Notes and limitations

  • params follows JSON representation: JSON arrays map to MiniZinc arrays; numbers, strings, and booleans map to their native MiniZinc types. Exotic types like sets and enums are not fully expressible this way.
  • Do not combine all_solutions with max_solutions; the MiniZinc driver rejects the combination.
  • MiniZinc requires a solver that supports the model (e.g. chuffed/gecode for CP, highs/cbc for MIP models). Use list_solvers to see what is installed.
  • Solutions are returned inline in the tool result; read_only_hint is set on all tools, so they do not modify your files or system.

Release files for minizinc-mcp 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for minizinc-mcp 0.1.0
File Size Uploaded
minizinc_mcp-0.1.0.tar.gz 11.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for minizinc-mcp 0.1.0
File Interpreter ABI Platform
minizinc_mcp-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 21.2 kB

Release files / minizinc_mcp-0.1.0.tar.gz

Download URL minizinc_mcp-0.1.0.tar.gz
Size 11.1 kB
Tags Source
SHA-256 checksum
How to use checksums
56884455b6204526e016f15391561a36e950c515832bf11637777a6e63a12c0f
BLAKE2b-256 checksum
How to use checksums
3f5fe950ab91d1710e7d710fd182118510a00684f82c4316d8d145a2de7e8691
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release files / minizinc_mcp-0.1.0-py3-none-any.whl

Download URL minizinc_mcp-0.1.0-py3-none-any.whl
Size 10.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
cb521b93565d49c48e72ae580cd1f7d676c8746112af16441659e1f55c163239
BLAKE2b-256 checksum
How to use checksums
89b89919c991dcd92cade7b58680e0283833b4d924a50212b163f011cfcfdf00
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page