Skip to content
SIMULATION
Model Context Protocol

Give an agent the engine. Never the gate.

Palletizer OS ships an MCP server. Point Claude, or any MCP client, at it and it can plan a pallet, validate a layout it rearranged itself, and prove a sealed plan has not been tampered with — against the same Python engine the CLI runs.

It cannot move anything. Not because we have not built that yet — because a model on the far end of a text channel is data to the process that owns the robot, and that is the property the whole architecture is designed around.

CLAUDE DESKTOP · CLAUDE CODE · ANY MCP CLIENT
{
  "mcpServers": {
    "palletizer": {
      "command": "uvx",
      "args": ["--from", "palletizer-full-stack", "palletizer-mcp"]
    }
  }
}

No clone, no virtualenv — uvx fetches the published package. Then ask it: “Plan a pallet for these 40 cases, verify it, and tell me what the validator did not check.” The last clause is the one worth asking.

OR: THE HOSTED SERVER, NOTHING TO INSTALL
{
  "mcpServers": {
    "palletizer": {
      "type": "http",
      "url": "https://palletizer-app.vercel.app/api/mcp"
    }
  }
}

Streamable HTTP, stateless, no account needed to start: POST https://palletizer-app.vercel.app/api/mcp. It speaks the same five spec revisions as the package and runs the same engine — a plan made through it has the content hash the CLI prints for the same input, which is the one claim here you can check yourself. Anonymous calls are rate-limited per minute; an Authorization: Bearer API key from a paid plan raises the limits and unlocks orders that span pallets. What each plan allows.

There is no motion tool, and there cannot be

Commanding a robot requires a capability token: a keyed MAC over the authorizing fields, minted inside the controlling Python process. An MCP client cannot mint one and there is no tool through which it could ask.

Two tests enforce it. One reads the tool registry and fails the build if any tool names a motion or authorization verb. The other asserts the stronger property — that the safety gate is not merely unexposed but not importable from the server module at all.

tests/test_mcp_server.py →
Try it without installing anything

The same six tools, running in this tab

The browser engine is a function-for-function port of palletizer_full/optimizer.py, checked placement-by-placement on thirteen datasets in CI. The hash below is a real SHA-256 over the same canonical JSON the Python side uses.
CALL A TOOL
WHAT THE AGENT RECEIVES · computed here, in this tab
Call optimize_pallet to begin. Every response below is real output from the same engine the Python core runs — proven identical placement by placement on thirteen datasets in CI.
Why verify_plan exists

A hash proves integrity. It does not prove honesty.

There are two attacks on a sealed plan and the hash only catches one of them. If someone edits a coordinate after the fact, the recorded hash stops matching and hash_verified comes back false. That is the easy case.

The digest is unkeyed. Anyone who can edit the document can also recompute it. So an attacker edits the geometry into something inadmissible, writes the verdict they want, and reseals — and the document verifies perfectly.

The only thing that catches that is running the validator again over the placements and comparing verdicts. That is what verdict_matches_geometry reports, and the red button in the console above builds exactly this forgery so you can watch it happen.

THE FULL SURFACE
optimize_pallet
Plan and seal a pallet
Plans a load, validates it, and returns a content-addressed artifact. Change one coordinate and the hash changes.
verify_plan
Prove a sealed plan is what it claims
Checks the hash, and separately re-derives the verdict from the geometry. The second check is the one that catches a forgery.
validate_stability
Check a layout you built yourself
The full validator over placements an agent rearranged — support, centre of mass, interpenetration, overhang. Not three scores.
check_reach
Would this arm reach this plan
Geometric pre-check against a robot's declared envelope and payload. Explicitly not an authorization.
list_robots
Supported arms and grippers
Every profile with its integration tier and the datasheet the numbers came from. Nothing is CERTIFIED.
ingest_wms_csv
Map a WMS export onto the box schema
Fuzzy header matching with per-field confidence and the rows it had to skip. Deterministic by default.
Resources and prompts, too

The server also serves the safety architecture, the known-risks list, the adapter contract and the robot profiles as MCP resources — so an agent can read what this software does not guarantee before it tells anyone a plan is safe. The review_pallet_plan prompt walks a plan the way a reviewer would: verify first, read the skipped checks second, and only then look at a metric.

Five protocol revisions, so your client works

MCP clients in the wild are pinned to different spec revisions, so the server speaks 2026-07-28 through 2024-11-05 — including the stateless server/discover handshake and per-request version negotiation. A client is never sent a field its revision does not define, and a version the server does not speak is refused with the supported list rather than silently downgraded. Zero dependencies: stdlib and this repository, so you can read the entire wire path.