Inspiration
I hate shopping online as it is today. Every e-commerce site assumes the retailer has to know the customer. Sizes, preferences, family members: either you re-enter them on every site, or you hand them over to be stored forever. Meanwhile, "AI shopping" mostly means a bot that clicks through the same UI a human would.
Adding a brain and tools to an ordinary website through WebMCP is revolutionary. The moment I came across WebMCP, I realized this is the future. I wanted to build a showcase application that shows how retailers can serve shoppers like me, who hate manual shopping, using WebMCP.
The user's AI agent already knows the user. The retailer already knows its products. WebMCP is the missing interface between them. So the guiding line for FitzYo became: your agent knows what fits you. The web doesn't have to.
The scenario that drove every decision was one sentence: "We're going to Hawaii for seven days in September. Plan what everyone should wear and find what we're missing."
What it does
FitzYo is an ordinary-looking apparel store with one difference: every commerce operation is also exposed to an AI agent through WebMCP, and the human and the agent share the same live page.
- Shop for your whole family without registering family members or storing measurements in the retailer's application.
- The store has no intelligence of its own. An external WebMCP-capable agent attaches to the page, discovers the tools, and shops using private context that lives only on the user's side.
- Tools are semantic, not DOM-based. search_products, filter_products, find_matching_variants, compare_products, get_size_guide, add_to_cart, propose_cart, and so on. Nothing clicks a button.
- The agent sends constraints, never the profile. The store learns "size XL, blue or black, not red, relaxed fit, under $80, label: Dad". It never learns Dad's chest measurement, and it rejects any payload that tries to include one.
- "Fits Dad ✓" badges appear on product cards. The agent registers each family member as derived constraints once, and the store badges every product that fits each person. The store never knows who Dad is.
- The human sees everything the agent does. Filters the agent set show as chips marked "✦ agent", with a count of how many products each one hides. An activity feed narrates every tool call. A plan panel and a day-by-day lookbook show the trip taking shape.
- The agent has to earn the cart. Cart tools are locked until the shopper grants the capability with a spend ceiling and an expiry, and the ceiling is enforced on every write. The shopper can revoke any tier at any time.
- Decisions come back to the human. ask_human pauses the agent with a question. propose_cart presents one priced, grouped basket that the shopper edits and accepts in a single action.
- There is no checkout tool. Ordering is a press-and-hold gesture the page only accepts from trusted input with a single-use nonce. Every line in the order records whether a human, an agent, or an accepted proposal put it there.
How we built it
- Elixir, Phoenix LiveView, and Ash Framework, deployed on Fly.io. One LiveView process owns the shared human/agent state: filters in the URL, results, selected product and variant, party members, capability grants, and the cart.
- Ash domains for the catalog (categories, products, variants, and structured size guides with per-size chest, waist, hip, and inseam ranges) and commerce (session carts and a human-only checkout). The seeded catalog has 56 products and 754 variants across Columbia, Patagonia, Nike, Levi's, Teva, and others.
- WebMCP registration in a LiveView hook. The page registers its tools on document.modelContext (and navigator.modelContext for the older spec) the moment a WebMCP surface appears, and also exposes a same-origin postMessage bridge for embedding shells. Every tool call round-trips over the LiveView socket and runs in the same process that renders the human's page, so the UI updates in the same frame as the reply.
- Any WebMCP agent can drive the store using the registered tools.
Challenges we ran into
- Agent state and user state. I wanted the site to work for user interaction and agent interaction at the same time. Making the agent's filters, badges, and recommendations first-class citizens of the same LiveView state, with clear provenance on every chip and cart line, took most of the design effort. The user can always tell which products the agent selected and which they selected themselves.
- Privacy that is enforced, not promised. Sending "size XL" instead of "chest 45 inches" sounds simple until the agent needs a size it doesn't have. The answer was to serve size-guide ranges from the store and have the agent match locally, then have the store actively reject measurement fields.
- Blocking tools inside a request/response protocol. ask_human, propose_cart, and request_capability need to wait minutes for a person. We had to make these calls suspend cleanly, allow one pending decision at a time, handle supersede and timeout as normal outcomes, and let the shopper keep using the store meanwhile.
- Human override that the agent respects. When the shopper removes a chip the agent set, the agent must not re-impose it. We surface removed_by_human in store state and flag re-imposition in the activity feed as a warning.
- State survival across remounts. Party members, grants, plan, and lookbook lived only in the LiveView process. A reload, a dropped socket, or clicking the logo silently dropped all of it while the cart carried on. Late in the build we moved agent session state into a session store and switched navigation to patches.
- Making checkout unreachable to agents without making it hostile. A press-and-hold gesture gated on trusted input and a nonce keeps a scripted click inert, while still feeling like a normal confirm to a person.
Accomplishments that we're proud of
- A store that looks and works like a normal retailer, where every commerce concept is also a structured, validated WebMCP capability.
- The "Fits Dad ✓" experience works end to end, and the retailer genuinely never receives who Dad is or what his measurements are.
- A capability model for agents: read and suggest on connect, cart by explicit grant with a spend ceiling, checkout never. The ceiling is enforced on every write, including accepted proposals.
- propose_cart: one priced basket with alternatives, optional lines, and per-person budgets, live budget math as the shopper edits, and a result the agent has to read rather than assume.
- Full provenance. Every filter chip, badge, and cart line knows whether a human, an agent, or an accepted proposal created it, and the order confirmation says so.
- A rehearsal script that runs the whole demo against a real browser with no LLM in the loop, which doubles as an executable specification of the tool surface.
What we learned
- Tool design is product design. The moment we named a tool after a UI element, the agent got worse. Naming tools after what the shopper wants (find_matching_variants, not click_size_dropdown) made both the agent and the human experience better.
- Agents need to see what humans see. get_store_state returning the human's overrides turned out to matter more than any search tool. Without it, an agent argues with the person.
- The retailer should serve data for reasoning, not do the reasoning. Structured size guides let the agent stay private and the store stay simple.
- Trust has to be granular and visible. A blanket "let the agent shop" is scary. "Let it fill a cart up to $500 for the next 30 minutes" is something people will accept.
- LiveView is a very good fit for WebMCP. Running tool calls in the same process that renders the page eliminated an entire class of sync bugs.
What's next for FitzYo
- Run the demo with real WebMCP agents as browser support lands, and publish the playbook as a reference for other retailers.
- Multi-retailer shopping. The same private context and the same agent, driving several stores' tool surfaces in one trip plan.
- Wardrobe feedback loop. Accepted orders flow back into the user's local wardrobe file, so the next trip starts from what they now own.
- Broader domains. Shoes, outdoor gear, travel, gifts: the architecture is not apparel-specific.
- Richer fit. Stretch, cut, length, and past-purchase fit feedback, so "Likely fits Dad" can become a confidence the agent explains.
- A portable private-context format, so a user's family, wardrobe, and preferences work with any agent, not just ours.
- Beyond apparel. The same approach works for flight booking or picking parts in a big-box hardware store.
Built With
- ash
- elixir
- javascript
- phoenix
- postgresql
Log in or sign up for Devpost to join the conversation.