Inspiration

I run the same office chores every week: reconcile an export, chase an overdue invoice, move an order from allocated to shipped, redact a contract before it goes out. A browser agent can already do all of this. Give one a task and it finds the buttons. The flaw showed up on day two: it acts live. I learned what it changed after it changed it, from a screenshot; if I was lucky.

The careful alternative, wiring an agent into each app by hand with guardrails and a review step, costs an integration per app, per team, forever. When Chrome and ChatGPT shipped WebMCP, the agent's tools and the person's screen could finally share one tab. That was the missing piece: authority could be graded instead of all or nothing, and the agent could build the very apps it needs instead of waiting on an integration. EEVEE is that bench (EEVEE like that Poket-Monster that has multiple evolutions). The agent builds a small app, proves it in my browser, and my passkey is the only key that publishes or writes.

How I built it

I built it solo during the submission period (25 August to 3 September 2026): about 23,500 lines across 164 files. The Office editors (Documents, Sheets, Slides, PDF) are about 155,000 lines I ported from my own private NON-WEBMCP predecessor project and released under Apache-2.0. Everything else, the applet model, the WebMCP tools, the sandbox, the passkey gates, is new.

The stack is Next.js 16, React 19, TypeScript, PostgreSQL 17, and Drizzle. Zod schemas validate every tool call twice: on the page, so an agent gets field-level errors without a round trip, and at the server. esbuild compiles agent-authored React in memory with an import allow-list, and the artifact runs in a sandboxed iframe whose content security policy blocks network, frames, and navigation. The only way out is a narrow window.eevee bridge.

The page registers 28 WebMCP tools. When a published run opens, the applet's own actions register as applet_* tools (Meridian Ops, the reference ERP, declares 32) and unregister when it closes. Reads answer at once. Every write first runs in a hidden rehearsal iframe against current data, and the decision card shows the exact fields before and after. The person approves with a passkey, rejects with a reason the agent reads back, or grants a small lease the server spends under an advisory lock.

Publishing requires a passing behavioral suite: declarative fill, click, press, wait, restart, and assertion steps that a browser worker runs against both the candidate and the currently published version.

The demo video is itself a small pipeline in video/: a CDP script drives a real Chrome through the whole flow with real executeTool calls and real pointer events, a Remotion composition lines zooms and callouts up with recorded marks, and the narration is text-to-speech.

Challenges

  1. Chrome's WebMCP surface is younger than the spec. executeTool hands input to the tool as a JSON string, calls execute(input) with no options argument, and swallows thrown errors, so an agent's bad call came back as nothing. We normalized the input, returned structured errors that name the failing field, kept the whole tool list under 48 KB of schema plus description, and wrote a headless-Chrome e2e script that exercises every tool the way an agent does so regressions in the browser show up in CI, not in a judge's tab.

  2. Making a passkey mean one thing. A fingerprint prompt that can be replayed is theatre. Each WebAuthn challenge is single-use and scoped to one exact operation: this version id, this action request, this lease. A write tool has to wait inline for a person who may take a minute, so the tool call blocks up to 45 seconds, await_action_decision covers longer, and a rejection carries the person's reason back as the tool result so the agent can change course instead of guessing.

  3. Proving the app before asking for the key. Running an ERP's order-to-cash scenarios inside the browser, against the live runtime, with evidence the person can read next to the source, took most of the trust budget: a sandboxed evaluation iframe, an evaluator injected into the applet, restart steps that prove durable state, and regressions recorded against the published version. Recording the demo found one more bug the tests had not: toggling the source view refetched the draft preview, which minted a fresh channel and reloaded the applet under a running runtime. Fixed the morning of the deadline.

What I learned

Rehearsal changes the conversation. Once the person sees "Foundry North · hold · false → true" instead of "the agent wants to call set_credit_hold," approvals take seconds and rejections come with reasons. Putting the tools on the page, where the person and the agent look at the same screen, is what makes that possible! no bespoke integration per app, no screenshot loop.

What's next

Typed edit tools for documents and slides (today the agent writes them only as whole files), agent-authored suites judged against the person's corrections, and the Meridian loop as a template for the six industry prompts on the landing page.

Built With

  • chrome-devtools-protocol-(e2e-and-screen-recording)
  • docker
  • drizzle-orm
  • esbuild-(applet-compilation)
  • gemini-tts-(narration)
  • gsap-(landing-motion)
  • konva-(slides)
  • next.js-16
  • pdf-lib-and-pdf.js-(pdf)
  • postgresql-17
  • postgresql-on-?-[provider]
  • react-19
  • remotion-(demo-video)
  • tiptap-(documents)
  • typescript
  • univer-(sheets)
  • vercel-(hosting)
  • vitest
  • webauthn-passkeys-(simplewebauthn)
  • zod-4
Share this project:

Updates

Submission history