pypddlengine
# pypddlengine
A Python PDDL engine and [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server that enables AI agents to interactively explore PDDL planning problems.
## Features
- **Standalone PDDL engine** — parse, validate, and execute PDDL domains and problems
- **Interactive plan exploration** — step through plans, query reachable actions, inspect world state
- **MCP server** — expose the engine as tools to any MCP-compatible AI agent (Claude Desktop, VS Code, etc.)
- **Python API** — direct programmatic access with structured JSON responses
- **Session logging** — record agent interactions to CSV/JSON for analysis
### Supported PDDL Features
| Feature | Requirement | Notes |
|---------|-------------|-------|
| STRIPS | `:strips` | Basic actions, positive/negative preconditions & effects |
| Typing | `:typing` | Typed objects/parameters, type hierarchies |
| Equality | `:equality` | `(= ?x ?y)` in preconditions |
| Negative preconditions | `:negative-preconditions` | `(not ...)` in preconditions and goals |
| Disjunctive preconditions | `:disjunctive-preconditions` | `(or ...)` in preconditions |
| Existential preconditions | `:existential-preconditions` | `(exists (?x - type) ...)` |
| Universal preconditions | `:universal-preconditions` | `(forall (?x - type) ...)` in preconditions |
| Conditional effects | `:conditional-effects` | `(when ...)` and `(forall ... effect)` |
| Implication | `:adl` | `(imply ...)` in preconditions |
| Numeric fluents | `:numeric-fluents` | `increase`, `decrease`, `assign`, `scale-up`, `scale-down` |
| Action costs / metric | `:action-costs` | `(total-cost)` with `(:metric minimize ...)` |
| Constants | — | `:constants` in domain |
### Unsupported PDDL Features
| Feature | Notes |
|---------|-------|
| Durative actions (`:durative-actions`) | Raises an explicit error with a descriptive message |
| Derived predicates (`:derived`) | Not parsed; will fail on load |
| Maximize metric | Only `minimize` is supported |
| Arithmetic in conditions | Numeric expressions like `(+ ?x ?y)` in preconditions are not supported |
## Installation
```bash
git clone https://github.com/kgoe-ait/pypddlengine
cd pypddlengine
uv sync
```
Or install from PyPI (once published):
```bash
pip install pypddlengine
```
## Usage
### Python API — Simulator
```python
from pypddlengine.engine import Simulator
sim = Simulator(domain_str, problem_str, plan_str)
sim.step_all()
print(sim.is_goal_reached())
```
Step through manually:
```python
sim = Simulator(domain_str, problem_str)
sim.step(("move", ("loc1", "loc2")))
print(sim.get_executable_actions())
print(sim.is_goal_reached())
```
### Python API — Exploration API
Higher-level API with structured JSON responses, designed for AI agent tool use:
```python
from pypddlengine.api import PDDLExplorationAPI
api = PDDLExplorationAPI(domain_str, problem_str)
actions = api.get_available_actions() # {"count": 4, "actions": [...]}
result = api.execute_action("move", ("a", "b")) # {"success": true, ...}
api.is_goal_reached() # {"goal_reached": false, ...}
api.reset()
```
### Session Logger
Wraps the exploration API and logs every interaction to CSV/JSON:
```python
from pypddlengine.session_logger import PDDLSessionLogger
session = PDDLSessionLogger(domain_str, problem_str, session_id="experiment_1")
session.execute_action("move", ["loc1", "loc2"])
session.export_to_csv("session.csv")
session.export_to_json("session.json")
session.print_summary()
```
### MCP Server (Claude Desktop)
Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json` on macOS):
```json
{
"mcpServers": {
"pddl-engine": {
"command": "uv",
"args": ["run", "python", "-m", "pypddlengine.server"],
"cwd": "/path/to/pypddlengine"
}
}
}
```
### MCP Server (VS Code)
Already configured in `.vscode/mcp.json` — works out of the box when opening this project.
### MCP Tools
Once connected, the AI agent can use these tools:
| Tool | Description |
|------|-------------|
| `pddl_init` | Initialize session with domain and problem PDDL strings |
| `pddl_init_from_files` | Initialize session from domain and problem file paths |
| `pddl_get_available_actions` | Get all executable actions in current state |
| `pddl_execute_action` | Execute an action by name and arguments |
| `pddl_get_current_state` | View all true predicates and fluents |
| `pddl_is_goal_reached` | Check if goal conditions are met |
| `pddl_reset` | Reset to initial state |
| `pddl_get_action_history` | Review actions taken so far |
| `pddl_get_domain` | Re-read the PDDL domain definition |
| `pddl_get_problem` | Re-read the PDDL problem definition |
## Running Tests
```bash
uv run pytest
```
## Project Structure
```
pypddlengine/
├── server.py # MCP server
├── api.py # Exploration API (structured JSON responses)
├── session_logger.py # Session logging wrapper
└── engine/ # Core PDDL engine
├── simulator.py # Plan simulation
├── parser/ # PDDL lexer & parser
├── interpreter/ # Domain/problem interpretation
└── execution/ # State management & action execution
```
## License
Apache 2.0 — see [LICENSE](LICENSE).
TDQS
Scored across 10 tools
Each tool targets a distinct aspect of PDDL exploration: initialization, action querying, execution, state inspection, goal checking, history, and domain/problem retrieval. There is no overlap or ambiguity.
All tools follow a consistent 'pddl_<verb>_<object>' pattern (e.g., pddl_init, pddl_get_available_actions, pddl_execute_action). The naming is uniform and predictable.
With 10 tools, the server is well-scoped. Each tool provides a necessary function for exploring PDDL problems without superfluous or missing functionality.
The tool set covers the full lifecycle of a PDDL exploration session: initialization, action enumeration, execution, state queries, goal detection, reset, history, and retrieval of domain/problem definitions. No obvious gaps remain.