sponsio

Contract testing for the tools your site exposes to AI agents.

npm version MIT licence GitHub stars

When your UI breaks, users complain. When the tools your site exposes to agents break, nothing happens — no error page, no support ticket. An AI shopping assistant just quietly fails to buy from you and buys somewhere else.

sponsio records the tools a page registers, commits that record to your repo, and fails the build when the contract changes underneath the agents already using it.

npm install -D sponsio puppeteer

npx sponsio snapshot https://shop.example -o sponsio.baseline.json   # record
npx sponsio check    https://shop.example                            # enforce

Puppeteer is an optional peer, so npm install sponsio alone will not pull it. Reading a live page needs a browser; sponsio diff, which compares two recorded snapshots, does not.

Source on GitHub npm Live drift tracker

Check your site

Loads the page in Chrome 152, records the tools it registers, and grades them. Takes about ten seconds. Read-only — no tool is ever called, and nothing is stored.

Not comfortable putting your URL in someone's box?

Run this in DevTools on your own site, then paste the result below. It never leaves your browser — the grading runs here, client-side, with no request to this server.

copy(JSON.stringify({sponsio:1,url:location.href,capturedAt:new Date().toISOString(),
  tools:(await document.modelContext.getTools()).map(t=>({name:t.name,description:t.description,
  inputSchema:t.inputSchema,annotations:t.annotations,kind:"imperative"}))}))

What a failure looks like

search_products
  breaking pillar   Allowed values removed: "toys". A tool call using one of
                    these now fails — often silently, as an empty result.
  breaking locale   New required property. Agents that omit it will fail.
  warning           Description changed. The model selects tools by
                    description, so this can change behavior with no schema change.

4 breaking · 1 warning · 1 safe

Two calls other tools get wrong

A changed description is a warning, not cosmetic

For a language model the description is the selection interface. Rewrite it and the model may stop choosing the tool, with the schema untouched and every test still green.

A dropped readOnly is breaking

Losing a readOnly or consequential annotation changes an action's blast radius without changing its shape. Schema-only diffing misses it entirely.

This page is agent-readable

Checking for WebMCP…

A tool that audits WebMCP contracts ought to expose one. This page registers its own tools through document.modelContext.registerTool, so an agent can read the install steps and the severity model without parsing this HTML. All of them are readOnly — a documentation page has nothing to destroy, and saying so is part of the contract.

In CI

- uses: njp-coder/sponsio@v0
  with:
    url: https://shop.example
    baseline: sponsio.baseline.json

Watching the whole web

The same diff engine runs nightly against every site in the public WebMCP directory — 553 sites, 3,648 tools — as webmcp-drift. Most nights nothing changes. The record only exists because something was watching the night before.