Skip to main content
Glama
README.md
# Z3/SMT MCP Server

An MCP (Model Context Protocol) server that exposes Z3/SMT solver capabilities for constraint solving, logical reasoning, and satisfiability checking.

## Features

- **Direct Z3 Python code execution** - Run arbitrary Z3 Python code
- **SMT-LIB 2.0 support** - Parse and solve SMT-LIB format problems
- **Constraint checking** - Check satisfiability of constraint lists
- **Theorem proving** - Prove theorems by showing unsatisfiability of negation
- **Expression simplification** - Simplify Z3 expressions
- **Logic program solving** - Parse and solve structured logic programs (Logic-LLM format)
- **Session management** - Incremental solving with push/pop support

## Installation

```bash
# Using pip
pip install z3smt-mcp

# Or install from source
git clone https://github.com/z3smt-mcp/z3smt-mcp
cd z3smt-mcp
pip install -e .
```

### Requirements

- Python >= 3.10
- z3-solver >= 4.12.0
- mcp >= 1.0.0

## Usage

### Running the Server

```bash
# Run directly
z3smt-mcp

# Or via Python
python -m z3smt_mcp.server
```

### Claude Desktop Configuration

Add to your Claude Desktop config (`claude_desktop_config.json`):

```json
{
  "mcpServers": {
    "z3smt": {
      "command": "z3smt-mcp"
    }
  }
}
```

Or if installed from source:

```json
{
  "mcpServers": {
    "z3smt": {
      "command": "python",
      "args": ["-m", "z3smt_mcp.server"]
    }
  }
}
```

## Available Tools

### `solve`

Execute Z3 Python code directly. All Z3 imports are pre-loaded.

```python
# Example: Solve a system of linear equations
x = Int('x')
y = Int('y')
solver = Solver()
solver.add(x + y == 10)
solver.add(x - y == 4)
if solver.check() == sat:
    print(solver.model())
# Output: [y = 3, x = 7]
```

### `solve_smtlib`

Solve problems in SMT-LIB 2.0 format.

```smt2
(declare-const x Int)
(declare-const y Int)
(assert (= (+ x y) 10))
(assert (= (- x y) 4))
(check-sat)
(get-model)
```

### `check_sat`

Check satisfiability of a list of constraints with automatic variable detection.

```json
{
  "constraints": ["x + y == 10", "x > 0", "y > 0", "x < y"]
}
```

### `prove`

Prove a theorem by showing its negation is unsatisfiable.

```json
{
  "theorem": "Implies(And(x > 0, y > 0), x + y > 0)",
  "variables": {"x": "int", "y": "int"}
}
```

### `simplify`

Simplify a Z3 expression.

```json
{
  "expression": "And(x > 0, Or(x > 0, y > 0))"
}
```

### `solve_logic_program`

Solve structured logic programs in Logic-LLM format.

```
# Declarations
Color = EnumSort([red, green, blue])
assign = Function(Object -> Color)

# Constraints
assign(obj1) != assign(obj2)
Distinct([c:Color], assign(c))
```

### Session Management Tools

- `session_add_variable` - Add a variable to the session
- `session_add_constraint` - Add a constraint to the session
- `session_check` - Check satisfiability and get model
- `session_push` - Push a new context (for backtracking)
- `session_pop` - Pop context (backtrack)
- `session_reset` - Clear the session
- `list_sessions` - List all active sessions

## Examples

### Solving Sudoku

```python
# Create a 9x9 grid of integer variables
X = [[Int(f"x_{i}_{j}") for j in range(9)] for i in range(9)]

solver = Solver()

# Each cell contains a value in 1-9
for i in range(9):
    for j in range(9):
        solver.add(And(X[i][j] >= 1, X[i][j] <= 9))

# Each row has distinct values
for i in range(9):
    solver.add(Distinct(X[i]))

# Each column has distinct values
for j in range(9):
    solver.add(Distinct([X[i][j] for i in range(9)]))

# Each 3x3 box has distinct values
for box_i in range(3):
    for box_j in range(3):
        box = [X[3*box_i + i][3*box_j + j]
               for i in range(3) for j in range(3)]
        solver.add(Distinct(box))

# Add known values (example)
solver.add(X[0][0] == 5)
solver.add(X[0][1] == 3)
# ... more constraints

if solver.check() == sat:
    m = solver.model()
    for i in range(9):
        print([m[X[i][j]] for j in range(9)])
```

### Bit-Vector Arithmetic

```python
# Solve for x where x * 3 == 21 in 8-bit arithmetic
x = BitVec('x', 8)
solver = Solver()
solver.add(x * 3 == 21)
if solver.check() == sat:
    print(solver.model())
```

### Array Theory

```python
# Find an array where a[0] + a[1] == 10
a = Array('a', IntSort(), IntSort())
solver = Solver()
solver.add(a[0] + a[1] == 10)
solver.add(a[0] > 0)
solver.add(a[1] > 0)
if solver.check() == sat:
    print(solver.model())
```

## Credits

- Z3 solver implementation adapted from [Logic-LLM](https://github.com/teacherpeterpan/Logic-LLM)
- MCP interface inspired by [clingo-mcp](https://github.com/newjerseystyle/clingo-mcp)
- Z3 Theorem Prover by Microsoft Research

## License

MIT License

TDQS

A3.6/5.0

Scored across 13 tools

Disambiguation4/5

Most tools have clear distinct purposes, but check_sat, session_check, and solve all involve satisfiability checking and could cause confusion if descriptions are not carefully read. The session_* family is well-grouped.

Naming Consistency4/5

Uses snake_case consistently, but some tools are single verbs (prove, simplify, solve) while others use noun_verb_noun pattern (session_add_constraint) or verb_noun (check_sat, list_sessions). The session_ prefix provides grouping but introduces inconsistency.

Tool Count5/5

13 tools is appropriate for an SMT solver server, covering constraint solving, session management, multiple input formats, and theorem proving. Not too few or too many.

Completeness4/5

Covers core SMT operations well: standalone checking, session management, multiple input formats, and simplification. Minor gap: standalone check_sat may not return model, but session_check does. No explicit session deletion, but reset suffices.

Maintenance

ActivityInactive
ResponsivenessNo issues