Model Context Protocol

Let an agent check the cart before it sells

The extension puts the guardrail where people shop. This puts it where agents shop. PatchTest runs as an MCP server, so anything that speaks the protocol can send it a cart and get back a verdict per item with the rule and the source behind it, before it recommends, adds or buys anything.

Claude Code, one line

claude mcp add --transport http patchtest https://patchtest.fly.dev/api/mcp

No key, no account, nothing to install. Every tool is read-only: nothing an agent can reach from here edits a rule, sets a verdict, stores a profile or spends a YouCam unit.

Add it

  1. 1

    Claude Code

    Run the line above. That is the whole thing. It is an HTTP server, so there is nothing to clone and nothing to keep running.

  2. 2

    Claude Desktop, Cursor, VS Code, anything else over HTTP

    Add a server of type http and paste the endpoint:

    https://patchtest.fly.dev/api/mcp

  3. 3

    A client that only speaks stdio

    Some clients cannot take an HTTP server. mcp/stdio.mjs in the repository is a pipe to the same endpoint and needs nothing but Node:

    { "mcpServers": { "patchtest": { "command": "node", "args": ["/path/to/patchtest/mcp/stdio.mjs"] } } }

    Pass a different endpoint as the first argument, or set PATCHTEST_MCP_URL, to point it at a local pnpm dev.

What it gives the agent

  • check_cartCheck a skincare cart

    Judges a cart. One verdict per item, each carrying the rule that produced it, the source URL and a quote from that source.

  • list_rulesList the rules

    The whole rule corpus, with every source, every quote and every caveat, including the seven rules whose source says less than the rule does.

  • list_scansList the recorded skin scans

    The recorded skin scans a check can be judged against. Each concern comes back with the measured score and the display score side by side.

What comes back

Ask it about a cart with an adapalene gel in it, for someone eight weeks pregnant, and the agent reads this:

BLOCK  Adapalene 0.1% Gel
  [R-PREG-01] Not for you right now. Retinoids are the one group that
    pregnancy skincare guidance consistently says to avoid, including
    the over-the-counter ones.
    instead: Azelaic Acid 10% Cream ($26) [LL-111]
    source says: "It is generally recommended to avoid topical retinoid
    medications."
    aad.org/public/everyday-care/skin-care-secrets/routine/pregnancy-skin-care

Trimmed. The real result also carries a second source for that rule, a second finding because the scan read Fitzpatrick V, and the same thing again as structured JSON for a caller that would rather parse than read.

The part that matters for an agent

  • The verdicts are not the model’s. They come from a deterministic engine over 24 cited rules. The server’s own instructions tell the calling model, in as many words, that they are not its to rewrite, soften or overrule, and that it should show the shopper the reason rather than assert the conclusion in its own voice.
  • An item it cannot read comes back UNKNOWN, never OK. That means the title named no active ingredient or strength, so no rule could apply. It is not a safety clearance, and the tool result says so in the same breath. The same goes for a cart with no findings: the corpus is finite.
  • Nothing here writes anything. There is no tool that edits a rule, sets a verdict, spends a unit or keeps a profile, and a test asserts every tool carries readOnlyHint.
  • One engine, not two. The judging is lib/check-cart.ts, which the extension’s endpoint calls too, so a browser and an agent cannot drift apart.

If something goes wrong

The client connects but lists no tools
It is probably speaking the deprecated HTTP+SSE transport and opening with a GET, which this endpoint answers with 405. Use the stdio bridge in step three instead.
Every item comes back UNKNOWN
The titles are being paraphrased before they reach the tool. The rules key on active ingredients and strengths, so pass titles as the shop writes them. “Retinol 0.3% Night Serum”, not “a retinol serum”.
Nothing fires even though the cart looks risky
Most rules key on the declared intake, so send one. Without an age band, a pregnancy status and the actives the shopper already uses, there is very little for the engine to decide on. Rules that key on a measurement need a scanLabel as well; call list_scans for the labels that exist.
A swap points at a product that is not in your shop
Swaps resolve against our fictional catalogue, because that is the only one we can price. Treat the returned name as the shape of the substitute, an azelaic acid cream rather than a retinoid, and match it to your own stock.

docs/MCP.md has the worked curl call and the one place this deliberately departs from the transport spec. The endpoint answers both the handshake-era revisions and the stateless 2026-07-28 one.