Skip to main content
Glama
szeider
by szeider

MCP Solver

License: MIT Python Version

An MCP server for constraint solving (SAT, MaxSAT, SMT, CP, ASP, DP). It turns the connected LLM host into a solver-writing agent: the host gets a Python kernel preloaded with a real solver library, modeling instructions for the chosen backend, and a submission gate. The host encodes the problem, runs and verifies it against the real solver, and submits the final program — the outcome is the solution plus the verified solver program that produced it.

Version 4 is a complete re-architecture. Both the MCP interface and the solving engine changed; the design from the SAT 2025 paper (v3) lives on unchanged on the v3 branch. See From v3 to v4 below.

The MCP server

mcp-solver-serve runs over stdio and works with any MCP host: Claude Desktop, Claude Code, Cursor, or your own client. The host LLM does the solving itself — the server is a solver toolkit; it runs no LLM and needs no API key:

  • select_backend(solver) sets up a persistent IPython kernel with the backend's solver library and helper functions, and returns the modeling instructions for that backend. Calling it again recycles the kernel for the next problem.

  • Kernel tools (python_exec, python_reset, python_status, python_interrupt) let the host write, run, and verify a real solver program; bare python_exec calls are routed to the solving kernel automatically.

  • submit_code(code) is the finish line: the final self-contained program is syntax-checked and, on success, stored and linked back as an MCP resource (mcp-solver://submissions/{id}), with the verdict as structured content.

  • Resources: mcp-solver://guide (backend selection and workflow) and mcp-solver://template/{solver} (the full modeling instructions, browsable without selecting).

  • Statistics (optional): set MCP_SOLVER_STATS=/path/to/stats.jsonl in the server's env to log one JSON line per solving episode — tool-call counts, execution failures, submissions, wall time. Host tokens are invisible to the server by protocol design; tool usage is the comparable metric across hosts. (submit_code results also carry a compact stats snapshot as structured content; the CLI path reports tokens and actual OpenRouter cost via --stats-json.)

Claude Desktop configuration, from a checkout (the working setup today, and the development path always; see Installation):

{
  "mcpServers": {
    "mcp-solver": {
      "command": "uv",
      "args": ["run", "--project", "/path/to/mcp-solver", "--extra", "agent", "mcp-solver-serve"]
    }
  }
}

Once the PyPI name transfer completes, no checkout will be needed. Until then this configuration fetches an unrelated stale v2.0.0 upload, so do not use it yet:

{
  "mcpServers": {
    "mcp-solver": {
      "command": "uvx",
      "args": ["--python", "3.14", "--from", "mcp-solver[agent]", "mcp-solver-serve"]
    }
  }
}

The server needs no API key — the model doing the solving belongs to the host. An OpenRouter key is required only for the command-line path below, which brings its own agent.

Related MCP server: mcp-optimizer

Requirements

  • Python 3.13 or 3.14 (not yet 3.15: the solver kernels run on the server's Python version, and ortools and python-sat publish no 3.15 wheels yet)

  • uv (a hard runtime requirement: solver libraries are supplied at solve time via uv run --with)

  • An OpenRouter API key — for the CLI and benchmark harness only; the MCP server itself runs without one

Installation

v4 is not yet installable from PyPI. The PyPI name mcp-solver is held by a third-party upload of stale v2.0.0 code, and PyPI blocks confusably similar names; a PEP 541 name-transfer request is pending. Until it resolves, install from a checkout:

git clone https://github.com/szeider/mcp-solver.git
cd mcp-solver
uv venv                         # Python 3.13 or 3.14, per pyproject.toml
uv pip install -e ".[agent]"

# OpenRouter key — only needed for the CLI path, not the MCP server:
mkdir -p ~/.config/coder
echo 'OPENROUTER_API_KEY="sk-or-v1-..."' > ~/.config/coder/.env

See INSTALL.md for details and troubleshooting.

Command-line use

The mcp-solver CLI runs the same solving pipeline without an MCP host, which is handy for scripts and benchmarks:

mcp-solver pysat "Place 8 non-attacking queens on an 8x8 board and give one solution."
mcp-solver pysat --problem tests/problems/pysat/n_queens.md

The solution JSON goes to stdout; the submitted solver program (e.g. n_queens_code.py) and a complete run log (run_*.json) land in the working directory.

Option

Description

--problem FILE

Read the task from a markdown file instead of text

--model NAME

Agent model: an alias like gpt56terra or a full OpenRouter ID (default: gpt56terra)

--workdir DIR

Working directory for the run (default: current dir)

--step-limit N

Maximum agent steps before stopping (default: 30)

-q, --quiet

Suppress per-step progress output

--dev [PATH]

Dev mode: take helpers and templates from a local checkout (bare --dev auto-detects; auto-on inside a checkout; also MCP_SOLVER_DEV)

--no-dev

Disable dev mode; use the published (PyPI-pinned) helpers

--stats-json FILE

Write the run statistics to FILE as JSON

From an editable clone, the CLI runs in dev mode: helpers and templates come from the source checkout (auto-detected), with one provenance line on stderr.

mcp-minion

The CLI runs mcp-minion underneath: a minimal ReAct agent over MCP, developed in this repo as the workspace package minion/. It is a lightweight, batchable substitute for a full MCP host such as Claude Desktop — point its standalone CLI at mcp-solver-serve (or any MCP server) to script what a chat host would do interactively (see minion/README.md). The default agent model is gpt56terra, the bundled alias for OpenRouter's openai/gpt-5.6-terra.

Backends

Each backend is selected as the first CLI argument (or via the select_backend tool). The right solver library is injected into the solve-time kernel automatically.

Backend

Domain

Solver library

pysat

Boolean satisfiability (SAT)

python-sat

maxsat

Weighted optimization

python-sat (RC2)

z3

SMT solving / verification

z3-solver

cpmpy

Constraint programming (CP)

cpmpy

clingo

Answer Set Programming (ASP)

clingo

didp

Dynamic programming (DIDP)

didppy

MiniZinc mode from v3 is retired; constraint programming is now covered by CPMpy. The didp backend is based on domain-independent dynamic programming (Kuroiwa & Beck; solved with didppy's anytime beam search): problems are modeled as state transition systems, a natural fit for routing, sequencing, scheduling, and packing.

How it works

The base mcp-solver package is a dependency-free solver helper library (mcp_solver.helpers.{pysat,maxsat,z3}; the CPMpy, Clingo, and DIDP backends need no helper module). It is never pip-installed into your environment; instead it is injected into each solve-time kernel via uv run --with mcp-solver==<version>, alongside the backend's solver library. This keeps the host environment clean and each solve reproducible.

Each backend ships a project template: a markdown prompt (package data) with the encoding conventions, output format, and helper API for that solver. The template goes to whoever solves: an MCP host receives it from select_backend; the CLI hands it to its mcp-minion agent as the system prompt. Either way, the solving LLM drives the write → execute → verify loop in a persistent IPython kernel — the ipython_mcp server from agentic-python-coder — and must end the solve by calling submit_code with the final self-contained program (syntax-checked server-side, never written to disk by the kernel). On the MCP path the accepted submission is linked back to the host as a resource; on the CLI path the client extracts the last successful submission, writes it to <basename>_code.py, and re-executes it in a fresh uv kernel to produce the answer.

Benchmark harness

mcp-solver-bench runs the bundled test problems in tests/problems/<solver>/ end-to-end and validates each result against a per-problem *_ground_truth.py validator (which reads the solution JSON on stdin and returns {"valid": ..., "message": ...}).

# Benchmark every backend
mcp-solver-bench

# Specific backends, several runs each, in parallel
mcp-solver-bench pysat z3 --runs 3 --jobs 4

Each run is bounded by --step-limit (default: 30 agent steps), and results are appended to results.jsonl in the output directory.

The same problems are also runnable as pytest end-to-end tests (uv run pytest minion/e2e_tests -k didp), and mcp-solver-runfolder <solver> <problem> <dir> materializes a standalone mcp-minion run folder for any of them.

Current status: in our runs with gpt-5.6-terra, all 30 bundled test problems solve correctly, including the four didp problems (TSPTW, knapsack, weighted tardiness, talent scheduling), each solved to proven optimality in every run. The MCP server path is validated with Claude Opus as host: 229/229 instances across CP-Bench (101) and ASP-Bench (128) solve correctly under strict semantic validation, as do the bundled SAT, MaxSAT, and SMT problems.

From v3 to v4: a new architecture

The SAT 2025 paper, "Bridging Language Models and Symbolic Solvers via the Model Context Protocol", documents v3: an MCP server exposing model-editing tools (add_item, replace_item, solve_model, …) through which a chat LLM builds up a solver model item by item, with solving happening inside the server.

v4 follows the IPython-kernel approach laid out in the CP-Agent (LLM4Code 2026) and ASP-Bench (NSE '26) papers: instead of a host LLM editing a model through protocol tools, a dedicated coding agent works in a persistent IPython kernel, where it iteratively writes an actual Python solver program, executes it against the real solver, verifies the result independently, and only then submits the program as the answer.

v3 (SAT 2025 paper)

v4 (CP-Agent / ASP-Bench approach)

Who does the work

The host chat LLM, via MCP editing tools

The host LLM (or mcp-minion for batch runs), as a solver programmer

Unit of work

Model items (add_item, solve_model, …)

A complete, runnable Python solver program

Execution

Inside the MCP server

In a persistent IPython kernel (ipython_mcp)

Verification

Manual, by the host LLM

Built into the loop: run → check → submit_code

Artifact

Transient model state

A verified, re-executable program you keep

Host interface

Many fine-grained model-editing tools

A solving kernel: select_backend, python_exec, submit_code

Backends

MiniZinc, PySAT, MaxSAT, Z3, ASP

PySAT, MaxSAT, Z3, CPMpy, Clingo, DIDP

Citations

  • Stefan Szeider, "Bridging Language Models and Symbolic Solvers via the Model Context Protocol", SAT 2025. Documents the v3 architecture (v3 branch). DOI 10.4230/LIPIcs.SAT.2025.30

  • Stefan Szeider, "CP-Agent: Agentic Constraint Programming", in Proceedings of the 3rd International Workshop on Large Language Models For Code (LLM4Code 2026), pages 6–13, ACM, 2026. The IPython-kernel approach behind v4. DOI 10.1145/3786181.3788711

  • Stefan Szeider, "ASP-Bench: From Natural Language to Logic Programs", in Proceedings of the 2026 IEEE/ACM 2nd International Workshop on Neuro-Symbolic Software Engineering (NSE '26), pages 1–8, ACM, 2026. The verification-gated benchmark methodology used by v4's test problems. DOI 10.1145/3786168.3788402

License

MIT; see LICENSE.

Available Tools

6 tools
python_execA

Execute Python code in the persistent solving kernel.

Runs in the kernel set up by select_backend unless kernel_id overrides it. State persists across calls (variables, imports). Raise timeout (seconds, max 300) for long solver runs.

ParametersJSON Schema
NameRequiredDescriptionDefault
codeYes
timeoutNo
kernel_idNo

TDQS

A3.6/5.0
Behavior3/5

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

No annotations, so the description carries the full burden. It usefully discloses that state (variables, imports) persists across calls and that timeout caps at 300 seconds, but says nothing about error behavior, sandboxing, or how execution output is captured/returned.

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

Conciseness5/5

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

Four short lines, purpose front-loaded, with each remaining sentence adding a distinct operational fact (kernel source, state persistence, timeout cap). No filler or restated name text.

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

Completeness3/5

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

No output schema exists, yet the description never describes what an execution returns (stdout, errors, result value), which is a meaningful gap for a code-execution tool. Kernel selection, persistence, and timeout behavior are covered, so the definition is workable but not complete.

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

Parameters4/5

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

Schema description coverage is 0%, so the description must compensate, and it does for two of three params: kernel_id is explained as overriding the kernel established by select_backend, and timeout is defined in seconds with a max of 300. The 'code' param is left implicit but is self-evident from the tool purpose.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Execute Python code') and adds the key qualifier that it runs in the persistent solving kernel, which differentiates it from a one-shot execution. It references select_backend for kernel setup, but never contrasts itself with submit_code, so sibling distinction is only partial.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives implied usage guidance: raise the timeout for long solver runs, and rely on state persisting across calls. However, it never says when to prefer this over submit_code or when to instead use python_interrupt/python_reset, so the caller must infer routing.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

python_interruptB

Interrupt running code in the solving kernel (state is preserved).

ParametersJSON Schema
NameRequiredDescriptionDefault
kernel_idNo

TDQS

B3.2/5.0
Behavior3/5

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

No annotations are provided, so the description carries the full burden. It does disclose one meaningful trait — that state is preserved rather than discarded — but says nothing about what happens if nothing is running, whether interruption is cooperative, permissions, or the result of the call.

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

Conciseness4/5

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

A single front-loaded sentence with no filler; the verb and effect lead the reader immediately. It is efficient, though it is arguably too terse for the behavioral gaps it leaves.

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

Completeness3/5

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

For a one-parameter tool with no output schema and no annotations, the description covers purpose and one behavioral note. It omits how to target a specific kernel and what the caller observes after interrupting, leaving the agent to guess at invocation details.

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

Parameters2/5

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

One parameter (kernel_id, nullable, default null) has 0% schema description coverage, and the description adds no meaning: it never explains what kernel_id identifies, that it is optional, or what the default targets. The 'solving kernel' phrasing hints at a default target but is not tied to the parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('interrupt') and resource ('running code in the solving kernel'), plus a scope qualifier ('state is preserved') that separates it from python_reset. It does not name siblings explicitly, so the differentiation is inferable rather than stated.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the verb: call it when running code needs to be stopped without losing kernel state. There is no explicit guidance on when to prefer this over python_reset, nor any prerequisite or condition (e.g., only valid while execution is in flight).

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

python_resetA

Create a new kernel (no kernel_id) or reset one (with kernel_id).

Prefer select_backend, which installs the right solver packages for you. The kernel created or reset here becomes the target of bare python_exec calls.

ParametersJSON Schema
NameRequiredDescriptionDefault
packagesNo
kernel_idNo

TDQS

A3.7/5.0
Behavior3/5

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

With no annotations, the description carries the behavioral burden. It usefully discloses that the created or reset kernel becomes the target of bare python_exec calls, but it does not mention that resetting may discard existing kernel state, nor does it explain the packages parameter's effect.

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

Conciseness5/5

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

The description is three short sentences with no wasted text. The main behavior is front-loaded, followed by the alternative tool guidance and the downstream effect on python_exec.

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

Completeness2/5

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

For a two-parameter, state-changing tool with no annotations, no output schema, and 0% schema description coverage, the description is incomplete. It covers purpose and one parameter but leaves packages undocumented and does not describe reset side effects or state loss.

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

Parameters2/5

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

Schema description coverage is 0%, so the description must compensate for both parameters. It explains kernel_id's effect well by describing create-without vs reset-with, but it completely omits the packages parameter, leaving half the parameters undocumented.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description gives a specific verb and resource, and it clearly distinguishes the two modes: no kernel_id creates a new kernel, while a provided kernel_id resets one. It also names the related sibling tool select_backend, so the tool's role is immediately identifiable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly says to prefer select_backend when solver packages are needed, which is useful routing guidance. The create-vs-reset condition is also clear, though the description does not explicitly state when not to use python_reset or what prerequisites exist.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

python_statusC

Check kernel state: active kernels, defined variables, packages.

ParametersJSON Schema
NameRequiredDescriptionDefault
kernel_idNo

TDQS

C2.9/5.0
Behavior2/5

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

With no annotations, the description carries the full burden of behavioral disclosure. 'Check' implies a read-only operation, but it does not explicitly state that it is non-destructive, nor does it describe side effects, authorization needs, or rate limits. It only lists what is inspected, which is minimal behavioral context.

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

Conciseness5/5

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

A single, front-loaded sentence with no filler. It efficiently conveys the core purpose in one clause.

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

Completeness3/5

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

For a simple no-required-parameter tool with no output schema, the description gives an outline of what is returned (kernels, variables, packages). However, it omits usage context and parameter semantics, leaving gaps an agent must infer.

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

Parameters2/5

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

The schema has 0% description coverage and the description never mentions the optional kernel_id parameter. It does not explain what the parameter does, when to supply it, or what the default behavior is when omitted.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb 'Check' and resource 'kernel state', and enumerates the inspected items (active kernels, variables, packages). It is clear but does not differentiate this tool from siblings like python_exec or python_interrupt.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No when-to-use guidance is given. The description does not say when to prefer this over python_exec or python_interrupt, nor does it state any prerequisites like requiring an active kernel.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

select_backendA

Start solving a constraint problem: call this FIRST, once per problem.

Sets up a persistent IPython kernel preloaded with the backend's solver library and helper functions, and returns the modeling instructions for that backend. Calling it again recycles the kernel for a new problem (previous session state is cleared).

Backends:

  • pysat: Boolean satisfiability — feasibility, combinatorial search

  • maxsat: weighted optimization over Boolean constraints

  • z3: SMT — integers/reals/bitvectors, proofs, program verification

  • cpmpy: finite-domain constraint programming — scheduling, assignment, puzzles

  • clingo: Answer Set Programming — logic rules, defaults, reachability

  • didp: dynamic programming (state-space search) — routing, sequencing, packing

Unsure which backend fits? Read the resource mcp-solver://guide first.

Then iterate with python_exec (write, run, verify against the problem statement), and finish by calling submit_code with the final, verified, self-contained program. UNSAT / "no solution exists" is a valid outcome.

ParametersJSON Schema
NameRequiredDescriptionDefault
solverYes

TDQS

A4.9/5.0
Behavior5/5

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

With no annotations, the description carries the full burden and delivers: persistent kernel lifetime, that re-invocation clears previous session state, that it returns modeling instructions, and that UNSAT is a legitimate terminal outcome. These are exactly the behavioral traits an agent needs and that the schema does not express.

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

Conciseness5/5

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

Front-loaded imperative first sentence, then setup behavior, then the backend list, then the workflow tail. The bulleted backend table is dense with information and every line earns its place; no filler.

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

Completeness5/5

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

No output schema exists, but the description says what is returned (modeling instructions) and sketches the full three-stage workflow ending in submit_code. For a single-parameter entry-point tool, an agent has everything required to select and invoke it correctly.

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

Parameters4/5

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

Schema coverage is 0% and the single 'solver' parameter has no enum, so the description must supply the value domain — and it does, enumerating all six backends with a one-line semantic gloss each (e.g. 'z3: SMT — integers/reals/bitvectors, proofs, program verification'). It does not explicitly state that these strings are the accepted values of the solver argument, so the mapping is inferred rather than stated.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Specific verb+resource: 'Start solving a constraint problem' and sets up a persistent IPython kernel preloaded with the backend solver library. It explicitly positions itself against siblings by naming the full workflow (python_exec to iterate, submit_code to finish), so an agent can place it without opening other schemas.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit when-to-use ('call this FIRST, once per problem'), re-use semantics ('Calling it again recycles the kernel for a new problem'), an escape hatch for uncertainty ('Unsure which backend fits? Read the resource mcp-solver://guide first'), and the follow-on tools. Nothing is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

submit_codeA

Submit the final, verified, self-contained solver program.

Call ONCE at the end, only after executing the program via python_exec and passing your verification. The code is syntax-checked; on success it is stored and linked as a resource (the server keeps the last 50).

ParametersJSON Schema
NameRequiredDescriptionDefault
codeYes

TDQS

A4.3/5.0
Behavior4/5

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

With no annotations, the description carries the full burden and does well: it discloses validation behavior (syntax-checked), the failure path, and what happens on success (stored and linked as a resource, server retains the last 50). It omits whether resubmission overwrites a prior submission and what an error response looks like.

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

Conciseness5/5

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

Three short sentences, front-loaded with the action and artifact, then the timing constraint, then the side effect. No filler and nothing repeated from the schema.

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

Completeness4/5

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

For a single-parameter submission tool with no annotations and no output schema, the description covers purpose, timing, validation, and persistence/retention. Remaining gaps (retry semantics, error format) are minor given the tool's simplicity.

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

Parameters4/5

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

Schema coverage is 0% and the schema itself only says 'code: string', so the description has to define the payload; it does so by specifying the code must be the final, verified, self-contained solver program. It stops short of stating language/format constraints, but the payload's required qualities are communicated.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb (submit) plus the exact resource (the final, verified, self-contained solver program), which is distinct from the sibling execution/status tools. It does not explicitly name which sibling it is contrasted with, but the artifact it accepts is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives explicit timing ('Call ONCE at the end'), an explicit prerequisite ('only after executing the program via python_exec and passing your verification'), and names the sibling tool involved. An agent cannot mistake when this should fire.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 6 tool updatesv4.1.0
    • First observedpython_exec
    • First observedpython_interrupt
    • First observedpython_reset
    • First observedpython_status
    • First observedselect_backend
    • First observedsubmit_code

TDQS

A3.6/5.0

Scored across 6 tools

Disambiguation4/5

Most tools are clearly distinct: python_status, python_interrupt, python_exec, and submit_code each have a unique role. The only mild overlap is between select_backend and python_reset (both create/configure kernels), but descriptions explicitly steer users to prefer select_backend, resolving the ambiguity.

Naming Consistency3/5

Four tools share a consistent python_<action> prefix (python_status, python_interrupt, python_exec, python_reset), but select_backend and submit_code break this pattern with a verb_noun convention. Two coexisting conventions make it mixed but still readable.

Tool Count5/5

Six tools is well-scoped for a constraint-solving workflow: backend setup, execution, kernel management, and final submission. Each tool earns its place with no redundancy.

Completeness4/5

The lifecycle (select_backend -> python_exec iterate -> submit_code, with status/interrupt/reset for kernel control) is well covered. Minor gaps: no tool to list or retrieve previously submitted solutions (only a resource mention), but core workflows are complete.

Maintenance

ActivityMaintained
ResponsivenessWithin a week

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP-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 solution
    21
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables solving Constraint Satisfaction Problems (CSP) like N-Queens, graph coloring, and Sudoku, as well as Linear Programming optimization problems through both MCP tools and HTTP API endpoints.
    2
    MIT
  • A
    license
    Not graded
    quality
    Not graded
    maintenance
    An MCP server that enables Large Language Models to interactively create, edit, and solve constraint models using backends like MiniZinc, Z3, PySAT, and Clingo. It bridges natural language with symbolic reasoning for solving complex logical, SAT, SMT, and optimization problems.
    MIT