Ferroplan
БесплатноНе проверенModel Context Protocol server for the ferroplan PDDL planner (solve / validate / decompose over stdio)
Описание
Model Context Protocol server for the ferroplan PDDL planner (solve / validate / decompose over stdio)
README
ferroplan
A fast, data-parallel PDDL planner in Rust — a deterministic planning core for the age of AI.
The bet: an LLM should be the author and supervisor of a planner, not its
runtime. The same reason you don't ask a model to add a column of numbers — you have
it emit code that does the arithmetic deterministically, and for free — applies one
level up: don't ask an LLM to be the planner for a whole village of agents. Have it
author a PDDL domain that then plans deterministically, cheaply, and inspectably at
scale, and let it only nudge that domain at runtime. PDDL is the auditable interface
between your intent, the model's authoring, and a fast solver — and ferroplan is
that solver.
Why PDDL, not prompt-spaghetti:
- Cost — a solved domain plans essentially for free; an LLM call per decision per agent does not.
- Determinism — same problem, same plan; you can regression-test it.
- Inspectability — you can read a domain and an axiom; you cannot read a model's weights.
- Scale — a village of agents each replanning is tractable for a fast solver, not as a wall of LLM calls.
▶ Try it live in your browser — pick a built-in example or paste your own PDDL; it plans entirely client-side via WebAssembly, no install. There's also a browser visualizer + block editor.
Where it stands
62% coverage across 22 IPC boards (3,916/6,366) on m5-air, including 381 certified optima.
| track | coverage | |
|---|---|---|
| net-benefit | 246/270 | ███████████████░ 91% |
| seq-sat | 503/580 | ██████████████░░ 87% |
| seq-mco t8 | 240/280 | ██████████████░░ 86% |
| seq-mco t4 | 237/280 | ██████████████░░ 85% |
| seq-mco t2 | 230/280 | █████████████░░░ 82% |
Best five shown. Full standings → STANDINGS.md · per-track detail, quality scoring and failure classes in benchmarks/ipc-standings.md.
ferroplan is a from-scratch reimplementation of the FF family of planners with a
data-oriented core (bitset states, structure-of-arrays / CSR operator tables),
enforced hill-climbing (EHC) with a best-first fallback, parallel grounding
and parallel heuristic evaluation, plus an SGPlan-style partition-and-resolve mode,
PDDL3 preference/metric optimization, and PDDL2.1 temporal planning (durative
actions). It ships both a library (with a structured, JSON-serializable API)
and the ff command-line binary — a drop-in for Metric-FF's
ff -o domain -f problem.
On classical and ADL benchmarks it runs within ~1.4× of the heavily-optimized C Metric-FF (EHC reaches goals in dozens of evaluations, not thousands); numeric trails and IPC-5 preference quality is competitive-not-winning — see Benchmarks.
Status: v0.22.0 —
ferroplan,ferroplan-cliandferroplan-mcpare on crates.io. APIs may shift before 1.0.
What's new in 0.22.0 — the coverage cycle, and the re-entries that ran hot. 58% coverage across 16 IPC boards (2,867/4,916), 373 certified optima — up from 53% across 13 boards last cycle. On the thirteen boards comparable to 0.21, coverage moves 2,153 → 2,248 (+95), the floor of this cycle's own ambition band; three long-dormant boards re-entered (propositional, net-benefit, constraints) and overshot expectations by a wide margin — net-benefit reaches 92%, the strongest board this cut. On the IPC-6 (2008) boards, ferroplan's raw coverage now clears the official 2008 track winners outright: 284/300 vs LAMA's 281/300 on seq-sat, 150/270 vs Gamer's 134/270 on seq-opt. Two boards moved backward and are named, not netted away (2014 seq-agile −1, 2014 tempo-sat −3). New this cut: docs/ipc-rankings.md, a rough per-year, per-track field placement against the actual IPC competitions. Full record: docs/roadmap-0.22.md.
What's new in 0.21.0 — the numeric cycle, and the ladders that pay their own way. The sailing wall is down: sailing-numeric was 0/20 in both prior releases — named in 0.20 as "a genuine numeric-reachability wall" and deferred — and is now 19/20, with block-grouping and pathwaysmetric off zero for the first time too. The temporal debt carried since 0.18 is paid: map-analyzer's three VAL-RED rows go green, and the twelve boards now carry zero VAL failures. The −26 regression the v0.19 backfill exposed in 0.20 is repaired and overshot — rung budgets are wall-denominated instead of fixed-pop, so novelty-light keeps its visit-all win while the searches it was starving come back. The optimal ladder learns the clock: a root informativeness gate decides whether LM-cut earns the remaining wall, taking LM-cut proofs from 13 to 53 and putting
scanalyzerandparc-printerin motion for the first time. Against 0.19 re-measured on the same machine, the twelve comparable boards go 1,943 → 2,132 (+189); standings 53% across 13 boards, 354 certified optima. Two boards stay behind and are named rather than netted away (tempo-sat −3, 2014 seq-opt −6, allcity-car). Every board here carries its own measured conditions. Full record: docs/roadmap-0.21.md.
Earlier releases are summarised in the changelog and its archive.
Features
- EHC + best-first — enforced hill-climbing with helpful actions (the FF
speed default), falling back to weighted best-first when it stalls. Selectable
per solve (
--search auto|ehc|best-first|…). - FF heuristic — delete-relaxation relaxed-plan heuristic over a
data-oriented task, deferred evaluation, tunable
g/hweights. - Data parallelism — parallel grounding and parallel batch heuristic
evaluation (
std::thread); the plan found is identical for any thread count. - PDDL coverage — STRIPS, typing, negative/disjunctive preconditions,
numeric fluents (Metric-FF style), ADL (conditional effects,
forall/exists, equality), and derived predicates / axioms (:derived, static/stratified — closed into the initial state via a datalog fixpoint). - PDDL3 preferences — soft goal preferences (incl.
forall-quantified and precondition preferences) compiled away, with anytime branch-and-bound metric optimization. (Exact-optimal on small/medium instances; best-found, flagged, on the largest — see Limitations.) - PDDL2.1 temporal —
:durative-actions withat start/over all/at endconditions & effects, constant or parameter-dependent durations, and required concurrency, via a decision-epoch forward search; output in the IPC temporal plan format (t: (action) [dur]) with a makespan. - SGPlan-style partitioning — an optional partition-and-resolve mode.
- Robust — a published library shouldn't crash: malformed/pathological PDDL (incl. deeply-nested forms) returns a typed error, never a panic.
- Structured output — the library returns typed,
serde-serializable results; the CLI emits classic FF text or JSON.
GUI
ferroplan-bevy is a Bevy app that visualizes a
domain+problem as a typed graph, animates the plan, and edits both problems and
domains in a Blockly-style block editor (cargo run -p ferroplan-bevy).

Install / build
# install the `ff` CLI from crates.io
cargo install ferroplan-cli # puts `ff` on your PATH
# …or build from a clone
cargo build --release # produces target/release/ff
cargo run --release --bin ff -- -o domain.pddl -f problem.pddl
As a library dependency: cargo add ferroplan (see Library below).
CLI (ff)
# drop-in: classic Metric-FF text output
ff -o domain.pddl -f problem.pddl
# structured JSON solution
ff -o domain.pddl -f problem.pddl --json
# pick a mode / search strategy
ff -o domain.pddl -f problem.pddl --mode partition
ff -o domain.pddl -f problem.pddl --search best-first --weight-h 3
# temporal (durative actions) — auto-detected; prints the IPC temporal plan
ff -o temporal-domain.pddl -f problem.pddl --mode temporal
# decompose a too-big temporal goal into ordered, individually-solved contracts
# (the "LLM authors, planner decomposes" bet, made inspectable — text or --json)
ff -o temporal-domain.pddl -f problem.pddl --mode temporal --decompose
# self-contained JSON job: {"domain": "...", "problem": "...", "options": {...}}
ff --json-request job.json
Run ff --help for all flags (--search, --weight-g/--weight-h,
--max-evaluated, --satisfice, --threads, …).
Library
use ferroplan::{solve, Options};
let domain = std::fs::read_to_string("domain.pddl")?;
let problem = std::fs::read_to_string("problem.pddl")?;
// Syntax-check before solving (no grounding/solving) — fast authoring feedback.
let report = ferroplan::parse(&domain);
assert!(report.ok, "{:?}", report.error);
let solution = ferroplan::solve(&domain, &problem, &Options::default())?;
if let Some(plan) = solution.plan {
for step in &plan.steps {
println!("{} {}", step.action, step.args.join(" "));
}
println!("metric: {:?}", plan.metric);
}
# Ok::<(), ferroplan::SolveError>(())
The public, serde-serializable surface: solve (plan a domain+problem),
decompose (split a too-big temporal goal into validated contracts),
parse (syntax-check + summarize PDDL without solving),
Session (ground once, replan many — for a live loop that re-solves the same
world every tick), and plan::validate_plan (independently check a plan). See
examples/ for solve, parse, json_api, and
replan (Session vs. re-solving from scratch, with timings).
Configuration
Every solver knob lives on one Options struct (library-first, serde-
serializable). The CLI flags and JSON job options map to the same fields; omitted
JSON fields fall back to the defaults shown.
ferroplan::solve(&domain, &problem, &ferroplan::Options {
mode: Mode::Auto, // auto | ff | partition | pddl3 | temporal
search: Search::Auto, // auto | ehc | best-first | ehc-then-best-first
helpful_actions: true, // helpful-action pruning (EHC)
weight_g: 1.0, // best-first path-length weight
weight_h: 5.0, // best-first heuristic weight (1·g + 5·h)
threads: 0, // 0 = auto
max_evaluated: None, // search node cap
optimize: true, // PDDL3: optimize metric vs. satisfice
..Default::default() // every field is optional
})?;
CLI equivalents: --mode, --search, --no-helpful, --weight-g/--weight-h,
--max-evaluated, --satisfice, --threads. Via JSON:
{"domain": "...", "problem": "...", "options": {"search": "best-first"}}.
Workspace layout
| crate | what |
|---|---|
| ferroplan | the library: engine + modes + solve / decompose / Session API |
| ferroplan-cli | the ff binary (clap + JSON) |
| ferroplan-mcp | an MCP server exposing solve / validate / decompose over stdio — so an LLM agent can author PDDL and drive the planner |
| ferroplan-bevy | Bevy app: visualize, inspect & animate a domain+problem (cargo run -p ferroplan-bevy [domain.pddl problem.pddl]) |
| ferroplan-wasm | WebAssembly binding behind the client-side browser demo — solve a domain+problem entirely in-page |
| ferroplan-py | Python binding (pip-installable extension module) exposing solve for embedding in Python tools |
Examples
examples/ collects worked domains that exercise the full feature set — see the examples index for a feature-by-feature map and a suggested reading order. Highlights:
- rpg — the clean intro: durative actions with renewable (workers) and consumable resources, gather → craft → build.
- rpg-world — a ~120-action crafting/economy domain (durative actions, numeric resources, renewable capacities, a reachability axiom) with a corpus of validated contracts, a flavor-×-scale suite/, an adversarial hard/ batch, and an industrial-city showcase that runs a whole metal/stone/wood industry as a pipeline of contracts.
- cabin — deep numeric build plus a durative "crew" twin (makespan vs. crew size, skill-gated scheduling).
- reachability — the worked derived-axiom
(
:derived) example: static transitive-closure reachability. - village — a full-ADL stress test (
when,forall+when,or, negation) over durative + numeric state. - villagers — a data-driven recipe planner with numeric PDDL3 metric optimization; the "embed in a game" model.
- logistics — transshipment: per-location goods, trucks with capacity, a train line.
- jobshop — scheduling with machine-exclusion (scales to 100 concurrent jobs).
- BORDERS.md — a measured map of where one-shot planning
solves vs. where a goal must be decomposed into contracts. The
decomposeAPI /ff --decomposeacts on that border: it splits a too-big temporal goal into ordered, individually-solved contracts and stitches them into one validated plan (e.g.hard/order-8→ 8 named contracts), falling back to a monolithic solve when a goal can't be split.
Benchmarks
ferroplan measures itself against three International Planning
Competitions — IPC-5 (2006), IPC-6 (2008), IPC-7 (2011) — every
deterministic satisficing track, at standard budgets with every plan
VAL-validated. The one honest table per competition (generated by
benchmarks/standings.py, refreshed each cut):
benchmarks/ipc-standings.md
— also rendered as the book's
Standings chapter.
Highlights: IPC-5 preference tracks are reference-scored from the
vendored official archive — on the qualitative track ferroplan
beats SGPlan5, the competition winner, 24–10 with 4 ties,
winning rovers, storage, and tpp outright — and the IPC-7
sequential multi-core track is entered under competition wall-clock
rules.
Classical and ADL coverage/speed are additionally measured against the C Metric-FF over a vendored subset. Headline (native Metric-FF, EHC default):
| category | ferroplan solved | speed vs Metric-FF |
|---|---|---|
| STRIPS | 40/40 | 0.71× (~1.4× slower) |
| ADL | 23/24 | 0.77× (~1.3× slower) |
| numeric | 36/40 | 0.22× |
Per-board detail: IPC-5 preferences benchmarks/ipc5-scoreboard.md / benchmarks/ipc5-qualitative-scoreboard.md; classical/numeric detail: benchmarks/results.md (and the project site). The comparison oracles are not bundled (GPL / non-commercial licences) — reproduce per benchmarks/COMPARING.md.
Profiling & perf tracking: PROFILING.md — a deterministic
metrics harness (benchmarks/perf.py run/compare against a committed baseline,
so improvement/regression is measurable across machines) plus the samply /
flamegraph / criterion-baseline workflow for finding and tracking hotspots.
Limitations
- Numeric trails Metric-FF: EHC's helpful-action lookahead stalls on some numeric domains and falls back to (complete, slower) best-first.
- IPC-5 preferences: compiled away, then optimized by an exact-closure metric optimizer with anytime sweeps, a diversified restart ladder, and the deterministically-budgeted ESPC penalty loop — all defaults. Coverage is full (48/48) on the vendored simple-preferences suite and ferroplan leads SGPlan5 under both quality conventions on three of the six domains (openstacks, storage, rovers), with trucks ahead on totals — see the scoreboard. The tpp/pathways p05–p08 tails still trail (best-found, flagged not proven optimal, measured direction-bound); the design record for the remaining work is in docs/espc-preferences-spec.md and docs/roadmap-0.5.md.
- PDDL3 trajectory constraints (
(:constraints ...)): the six untimed modal operators (always,sometime,at-most-once,sometime-after,sometime-before,at end) are enforced on the classical path — compiled into monitor automata and cross-checked by the independent verifier. Hard constraints latch a forced-terminal END action (linear in monitors — the 0.8 construction; goal-side compilation viaFF_NO_TRAJ_END=1); soft(preference name ...)constraints are priced through the PDDL3 metric machinery like native goal preferences (the IPC-5 qualitative-preferences suite is vendored and scored against the official IPC-5 field: ahead of SGPlan5, the track winner, 24W/4T/10L overall, winning three of five domains outright — see benchmarks/ipc5-qualitative-scoreboard.md). The timed operators (within,hold-during,hold-after,always-within) and the temporal path are still rejected by name rather than silently dropped (FF_CONSTRAINTS_REJECT=1restores the pre-0.7 blanket rejection). - Temporal: durative actions with constant, parameter-dependent, or
state-dependent durations and required concurrency are supported, and every
solved plan on the full IPC-2008/2011 tempo-sat corpus is VAL-validated
(399/630 at 30 s, 399/399 valid — see
benchmarks/ipc67-temporal.md). Coverage on
the remainder is search-limited: the recorded walls (machine-shop, storage,
model-train) are guidance problems, not semantics — and since the 0.14
extension,
over allinvariants are enforced on every happening, with object-symmetry orbits collapsing interchangeable-object state blowups (match-cellar 10/20 → 20/20, turn-and-open off zero). Duration inequalities ((>= ?duration L)/(<= ?duration U)/andranges) are supported — the search commits to the shortest feasible duration — as are timed initial literals ((at <time> <literal>)in:init) and?durationinside numeric effect expressions (duration-dependent effects). Continuous (#t) effects are not yet supported. - Derived predicates (
:derived): static/stratified axioms are supported (closed into the initial state); dynamic derived predicates (bodies over changing facts) are not yet.
Acknowledgments
This project is built in deep respect for the planners that came before it.
SGPlan (SGPlan5 / SGPlan6), by Chih-Wei Hsu and Benjamin W. Wah at the University of Illinois, has been the standard to beat in this corner of automated planning for the better part of two decades — the IPC-winning system whose constraint-partitioning and extended-saddle-point penalty-coordination ideas still define the state of the art for satisficing planning with preferences and with temporal/resource constraints. I've followed that line of research for many years, and to build something that even comes close to it on a slice of the benchmarks is, genuinely, an honor. Enormous credit to that team for the depth, rigor, and sheer durability of the work — ferroplan is in no small part an attempt to learn from it, in Rust.
Equal thanks to Jörg Hoffmann's FF / Metric-FF, whose relaxed-plan heuristic and enforced hill-climbing are the backbone of this engine; to the IPC organizers and domain authors whose benchmarks make progress measurable; and to Derek Long and Maria Fox's VAL, used here to independently validate the temporal plans.
Thanks also to Sean Chatman, whose downstream
fork drives ferroplan as the
deterministic core of a Claude Code agent control plane, and in doing so put
real pressure on the MCP and library surfaces. The optional schema feature
(typed JSON Schema for Options/Mode/Search instead of an opaque Value)
and the wasm set_timed_fact / world_bytes / mind_bytes bindings came from
that work; his stateful-session MCP server is the design we're measuring our own
against.
License
Dual-licensed under either of MIT or Apache-2.0, at your option.
Установка Ferroplan
У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.
▸ github.com/hhh42/ferroplanFAQ
Ferroplan MCP бесплатный?
Да, Ferroplan MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для Ferroplan?
Нет, Ferroplan работает без API-ключей и переменных окружения.
Ferroplan — hosted или self-hosted?
Self-hosted: сервер запускается локально на твоей машине командой из раздела установки.
Как установить Ferroplan в Claude Desktop, Claude Code или Cursor?
Открой Ferroplan на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Похожие MCP
GitHub
PRs, issues, code search, CI status
автор: GitHubFilesystem
Secure file operations with configurable access controls.
Memory
Knowledge graph-based persistent memory system.
Template MCP Server
A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure
автор: mcpdotdirectAmap Maps Mcp Server
MCP server for using the AMap Maps API
автор: duxiaohuiSupabase
Database, auth and storage
автор: SupabaseEverything
Reference / test server with prompts, resources, and tools.
Git
Tools to read, search, and manipulate Git repositories.
Sequential Thinking
Dynamic and reflective problem-solving through thought sequences.
Time
Time and timezone conversion capabilities.
Compare Ferroplan with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории development
