Pin the contract of every MCP tool you depend on. Fail CI when it changes behind your back.
Your package lockfile pins the code an MCP server ships. It does not pin what that
server tells your model to do — the tool names, descriptions and schemas your model reads
as instructions on every connection. Rug-pulls, tool poisoning, schema widening and annotation
flips are all text diffs on data you already receive. contractpin hashes that contract
(RFC 8785 canonical JSON → SHA-256) into a committed contractpin.lock and exits 1 the
moment anything moves.
curl -O https://open.getaxionlabs.com/contractpin/contractpin.py python contractpin.py init npx -y @acme/mcp-search # writes contractpin.lock — commit it python contractpin.py verify # exit 1 the moment anything moves
Python 3.9+, standard library only, one file, MIT. A TypeScript twin produces byte-identical digests; 19 conformance vectors make independent implementations checkable rather than trusted.
GitHub repository and package-manager installs: coming; this page is the canonical source until then.