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.
{
"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.
{
"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.
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 →The same six tools, running in this tab
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 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.
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.