Inspiration

Most shopping assistants rush you to checkout. They turn listings into confident recommendations, quietly drop constraints that are hard to meet, fill missing facts with guesses, and treat a "yes" in chat as permission to act. That goes badly when compatibility matters, like a drive that has to physically fit your laptop bay. I wanted to build the opposite: compare with evidence, cart with consent, never purchase on your behalf.

What it does

ShopSmart is a simulated Alexa+ shopping experience backed by a real, self-hosted MCP server (spec 2025-11-25, Streamable HTTP).

  1. Brief to criteria ledger. A natural-language request becomes a visible ledger of HARD constraints, SOFT preferences, MISSING info and UNVERIFIABLE fields. Hard constraints are never silently relaxed.
  2. Evidence-backed research. Products come back with specs, source links, verification timestamps, and conflicting or missing fields flagged. Every important claim is marked verified, provider claim, or Unknown.
  3. Constraint verification. Every candidate is checked against the ledger. Violations fail openly on the card and in the comparison, and failing products can't be proposed for the cart. That rule is enforced on the server.
  4. Explainable comparison. A side-by-side table shows prices, specs, warranty and a per-constraint verdict with evidence. Unknown delivery and tax costs are never treated as zero.
  5. Consent-bound cart. propose_cart_add creates a pending, fingerprinted, expiring action and doesn't change the cart. Only explicit approval of that exact proposal adds the item, and only once.
  6. Never purchases. There's no checkout, payment or order tool. You buy on the retailer's site yourself.

Search can run on a curated snapshot catalog or on live Amazon.in listings.

How I built it

  • MCP server: Express with the official @modelcontextprotocol/sdk, 13 Streamable HTTP tools (search_products, verify_product_requirements, compare_products, manage_shortlist, propose_cart_add, confirm_cart_add, get_cart and more), stateful sessions and an Origin allowlist.
  • Web app: Next.js (App Router), React, TypeScript and Tailwind, acting as a genuine MCP client (initialize, tools/list, tools/call), with browser voice input and spoken replies.
  • Data: PostgreSQL with Prisma for sessions, criteria, shortlist, cart, pending consent actions and audit events.
  • Deployment: Docker Compose on Amazon EC2.
  • Tests: 81 Vitest tests and 7 Playwright browser tests, including consent replay, expiry and concurrency cases, prompt injection, and purchase refusal.

Challenges I ran into

  • Multi-turn refinement: "change my budget" was wiping out the earlier constraints. I fixed it with proper merge semantics and regression tests.
  • Confirming cart changes: the UI's confirm route was hard-coded to the add action, so updates and removals couldn't be confirmed. It now validates any pending cart action on the server.
  • Hosting: MCP Streamable HTTP sessions are stateful, so serverless hosting didn't work. I moved to a persistent EC2 and Docker host.

Accomplishments that I'm proud of

  • Consent is enforced in the MCP tool layer, not in a prompt. Each approval is single-use, expires, and is tied to a fingerprint of the exact product and price.
  • Uncertainty is part of the output: unknown and conflicting data is shown, not smoothed over.
  • It works end to end with zero API keys.

What I learned

MCP makes it possible to enforce a safety boundary in one place. Keeping the shopper's constraints as durable state, not per-turn prompt text, is what keeps an assistant honest.

What's next

  • Connect to a real Alexa+ device
  • User authentication
  • More product categories
  • An LLM brief parser (Amazon Bedrock support is in the code but not yet live)
  • Scaling MCP sessions beyond a single replica
Share this project:

Updates

Submission history