Inspiration

My brother has a phone accessories store. Every time he restocks, he sends his supplier a message like:

2 cases of 6ft usb c braided black, 10 tempered glass for the 14 pro, 3 chargers

And then somebody on the other end sits down and turns that into SKUs by hand. In a wholesale catalog that last line might be listed as WL CHGR 65W SINGLE USB PRT BLK REMAX. It takes twenty minutes and usually a phone call to confirm. Every order, every week.

I assumed for a long time that this was a search problem. It isn't. Software that tries to solve it by matching ends up guessing, the buyer receives the wrong charger, and after that happens once nobody trusts the automation again. What the person on the other end is actually good at is knowing which lines they can fill and which ones they have to ask about.

What it does

Restock makes a distributor's ordering portal something an AI agent can operate directly. The demo storefront, Harbor Wireless Supply, has 243 SKUs named the way wholesale catalogs actually name things: abbreviations, inconsistent casing, pack units that don't match how buyers talk.

An agent passes the buyer's raw sentence to resolve_order and gets back a decision for each line.

  • Resolved, with the reason stated. "2 cases of 6ft usb c braided black" comes back as SKU 10009, Cable Usb-c 6ft Braided Black Premium, matched on cable, braided, USB-C, 6ft and black. The buyer said "cases" and the catalog sells EA, so Restock records both instead of quietly converting one into the other.

  • Needs clarification. "3 chargers" really is ambiguous in this catalog, so instead of picking one Restock returns what separates the candidates (product type) and the three actual options: charger, car charger, wall charger. The agent asks the buyer and calls choose_option with the answer.

  • Not found, said plainly. It never substitutes something close.

submit_order refuses while any line is still unresolved, the same way the portal's own Confirm button stays disabled.

Why WebMCP fits this problem

Catalog resolution can't live in the agent. The distributor is the one who knows the catalog, the pricing, the pack units, what's in stock, and what counts as ambiguous in their own inventory. An agent scraping the page would have to reconstruct all of that from rendered HTML, and it would guess in exactly the places where the distributor would have asked.

With WebMCP the site can publish that judgment as a tool contract instead. The agent handles the language, the site handles the catalog and decides what needs a question.

What people and agents can now do together

The part I find interesting isn't the matching, it's the question.

When Restock returns NEEDS_CLARIFICATION it's telling the agent: this one is mine to ask, here's what to ask, here are the options to offer.

That's backwards from how this normally works. Usually the agent decides when to bother the human. Here the website decides, because it's the one that knows where its own catalog is ambiguous, and the agent just carries the question to the buyer in whatever language the buyer speaks. The buyer answers once and the order closes.

How I built it

Next.js on Vercel. Five tools registered natively with document.modelContext.registerTool — no extension, no polyfill — and annotated so an agent knows which four only read and which one writes.

Behind the tools there's lexical search over the catalog, an LLM pass that splits a sentence into order lines with quantities and units, and a decision layer that compares the surviving candidates for each line and works out what actually distinguishes them. If they differ on exactly one attribute, that attribute becomes the question. I validated it against a set of real buyer phrasings before wiring up any of the WebMCP part.

The tools drive the same order draft the human UI does, so the application can't tell a tool call from a click. The order fills in on screen while the agent works.

Challenges I ran into

Getting the tools to work was easier than getting them to be honest.

My first version threw exceptions with genuinely useful messages, like "1 line still needs clarification". Agents never saw any of them — a thrown error arrives as a generic failure and the reason is gone.

I also rendered a WebMCP status line server-side for my own debugging. Agents that read the served HTML saw it say the tools weren't ready yet, believed it, and stopped before ever trying to call anything. That one cost me most of an afternoon.

And submit_order shipped with no annotations, so it wasn't classified as an action at all. Everything else was marked read-only, and the one tool that actually places the order was invisible as a thing an agent could do.

None of these were visible from inside the app. They only showed up when I started calling my own tools the way an agent would.

What's next

Restock is meant to be infrastructure rather than a storefront: a hosted tool layer a distributor can point at their own catalog. The one in the demo is synthetic. Ingesting a real catalog is the next piece.

Built With

Share this project:

Updates

Submission history