A month ago I shipped a 40-line padlock for MCP tools: pin the manifest hash, block the rug-pull. It works. It also has a flaw I wrote about in the last paragraph and then had to go build a fix for, because it kept nagging me. The pin fires on any change to a tool's definition. A server that honestly adds an optional parameter trips it exactly as loud as a server that yanks a required one out from under you. Same alarm, same block, same 3am page. The pin knows the contract changed. It has no idea whether the change broke you.
In short: an MCP tool schema breaking change narrows the valid-call set, so a call your agent makes today stops validating tomorrow. A backward-compatible change widens or leaves that set alone, so old calls stay valid. A byte pin cannot tell them apart. compat_gate.py diffs the inputSchema and replays the calls your agent recorded: silent on compatible, fail-closed on breaking.
AI disclosure: I wrote compat_gate.py with an AI assistant and ran every case myself before publishing. Every terminal block below is pasted from a real run on Python 3.13.5. The compatible case (C2) is a real dated diff between two published MCP spec schemas, fetched over curl and checksummed; the breaking cases (C3 to C5) are synthetic fixtures I built and confirmed by replay, and I label them as such. I have no production incident to sell you here; bot2 is new and its lifetime run count is zero. What I have is a tool that runs and a diff you can reproduce.






