Inspiration

Browser agents can now work across websites. That creates a privacy problem: proving one fact often means copying an entire private record into the agent conversation.

A fellowship may need to know that an applicant is over 18, enrolled, studying an eligible field, above a GPA threshold, and resident in an eligible region. It does not need the person's birth date, student ID, exact GPA, transcript, home address, or name.

Proof Courier started with one question: can the agent carry the answer without carrying the record?

What it does

Proof Courier is a working two-site WebMCP workflow backed by three independent production artifacts. The fellowship verifier publishes the five claims it needs, along with the audience, purpose, expiry limit, fresh nonce, prohibited fields, and a rule that only the person may submit.

The private wallet checks that request before preparing anything. Its Request Firewall blocks an unsafe audience, purpose, nonce, or request for automatic submission. If a site asks for raw records, extra claims, or a longer lifetime, the wallet releases nothing and returns a machine-readable counterproposal containing only the five derived claims and a ten-minute lifetime.

Once the verifier accepts that smaller request, the wallet prepares it for visible review. The agent still cannot export anything. The person sees what will be shared, who will receive it, why it is needed, and when it expires.

Only the person's approval registers wallet_export_proof. The tool works once and then disappears. The agent carries the proof to the verifier, which checks it and prepares the application. There is no agent tool for final submission.

The result is simple: five eligibility claims cross between the sites. The private source values stay inside the wallet.

Why WebMCP

This experience depends on structured tools and live page state.

The verifier gives the agent a precise request instead of making it guess from pixels. The wallet turns consent into real capability control. Before approval, export does not exist. After approval, it appears for one use. After that use, it is replaced by a read-only receipt.

That 0 to 1 to 0 capability lifecycle means the person and agent see the same authority state. It also gives the agent a safe recovery path when a website asks for too much.

The wallet and verifier run on separate origins. They do not share browser storage or fetch data from each other. In the tested journey, the proof returned by one WebMCP tool and passed to the other is the only bridge.

How we built it

Both pages register their own tools with document.modelContext.registerTool.

The synthetic proof bundle uses Web Crypto. A P-256 issuer signature authenticates the credential metadata. Merkle inclusion paths reveal only the requested claims. A holder signature binds the audience, purpose, nonce, expiry, disclosure set, approval time, and one-use consent grant.

The verifier rejects an untrusted issuer, wrong audience or purpose, expired proof, repeated nonce, missing or extra claim, altered disclosure, forged signature, or consent dated in the future.

The wallet, verifier, and showcase deploy as independent artifacts. Each canonical origin serves only its own routes and entry chunk. The 21-check production matrix returns 200 for the owning route and chunk, and 404 for every peer role route and peer entry chunk. Release checks also keep wallet signing fixtures out of verifier and showcase artifacts, remove source maps, scan for raw synthetic record values, and verify six security headers on every role.

Challenges

The hardest part was separating preparation from permission. A confirmation message was not enough. The agent's actual tool inventory had to change after the visible approval and change again after the permitted export.

An early version also included linkable identity metadata in otherwise safe receipts. We removed it and added checks around every agent-facing result. Privacy here is not a promise in the interface. It is a boundary tested in the data path.

The Request Firewall introduced a second challenge. Refusing a bad request is easy; helping the agent continue safely is harder. The wallet now explains why the request failed and, when possible, proposes the smallest acceptable replacement.

What we learned

Tool schemas are part of the trust model. A useful WebMCP tool needs clear inputs, bounded output, honest annotations, and a lifecycle that matches its authority.

We also learned where the human should remain in control. The agent is good at reading requirements, comparing policies, and carrying a proof. The person should approve disclosure and make the final consequential decision.

How we tested it

The release includes:

  • 78 of 78 unit and contract tests
  • 22 of 22 named adversarial privacy and authority scenarios
  • 10 of 10 Playwright checks, including six product journeys and four wallet durability and concurrency checks
  • 21 of 21 production route and entry-chunk isolation checks across the three role artifacts
  • 1 of 1 complete browser journey against independently served role artifacts
  • 5 direct tool smoke steps using GoogleChromeLabs webmcp-evals
  • a 100/100 tool audit with zero findings in Nekuda WebMCP Workbench
  • automated keyboard, 390px layout, and serious or critical accessibility checks

An earlier deployed build also passed a native WebMCP run in the OpenAI Codex in-app browser: five synthetic claims crossed, zero private fields crossed, export disappeared after use, verification passed, and no agent submission tool appeared. That native receipt predates the IndexedDB wallet wiring and says so. The final role-isolated release was rerun through the public browser harness after production promotion.

The public Evidence Room links the receipts, source revision, and limits behind these claims.

Scope

Every person, credential, institution, and application in the demo is synthetic. Proof Courier is an interaction and protocol prototype. Wallet export authority persists only in same-origin browser storage. Verifier challenge and replay state remain in memory and reset across reloads or application instances. It is not a production identity wallet, compliance product, W3C Verifiable Credential implementation, zero-knowledge proof, or real fellowship integration.

Try it

Built with

WebMCP, React, TypeScript, Web Crypto, Vite, Vitest, Playwright, GoogleChromeLabs webmcp-evals, Nekuda WebMCP Workbench, GitHub Actions, and Vercel

Built With

  • accessibility
  • cryptography
  • github-actions
  • playwright
  • privacy
  • react
  • typescript
  • vercel
  • vite
  • vitest
  • web-crypto
  • webmcp
Share this project:

Updates

Submission history