Inspiration

Embedded payments, authentication frames, editors, support widgets, and microfrontends often communicate through window.postMessage. When those integrations fail, developers see symptoms instead of causes: initialization vanishes, protocol versions drift, or a valid-looking message arrives from the wrong frame. Ordinary logs rarely preserve timing, event.origin, exact event.source identity, the developer's current selection, and the visible consequence in one place.

EmbedDoctor began with a simple question: what if the live browser boundary itself could become a shared debugging workspace for a developer and an AI agent?

What it does

EmbedDoctor turns invisible iframe failures into browser evidence, a reviewed boundary contract, and a verified repair.

The controlled checkout reproduces three real failure classes:

  1. Lifecycle race: INIT is sent before the payment widget installs its listener.
  2. Protocol drift: the host retries with protocol v1 while the widget accepts v2.
  3. Wrong frame identity: a same-origin sibling sends a valid-looking total update from the wrong WindowProxy, changing the checkout from $120.00 to $0.01.

The page records the actual message sequence, lifecycle state, origin, source classification, protocol version, policy verdict, and rendered result. An agent can inspect only the incidents selected by the developer, stage the smallest report-only contract justified by that evidence, replay the same seeded boundary, undo a proposal, and prepare an export.

After the developer reviews and approves enforcement, the same seed runs again. READY/ACK initialization succeeds, protocol v2 is required, the exact origin and iframe source are bound, the sibling message is blocked before the application handler, and the checkout remains $120.00.

Why WebMCP

The evidence that matters exists inside the active browser session. It includes the current incident selection, real MessageEvent.origin, strict event.source identity, iframe lifecycle, visible draft state, and rendered consequence.

A CLI, remote MCP server, or conventional API could support part of this workflow only after adding custom page instrumentation and state synchronization. WebMCP lets the owned page expose semantic operations directly beside the live interface, with no screenshot guessing or copied logs.

EmbedDoctor exposes five native tools:

  • embeddoctor.inspect_selected_incidents
  • embeddoctor.stage_boundary_contract
  • embeddoctor.replay_boundary
  • embeddoctor.undo_contract_change
  • embeddoctor.export_contract_bundle

Tool availability follows product state. Export is unavailable until a developer-approved contract passes an enforced replay. Every agent action appears in a provenance ledger as WebMCP; manual fallbacks are visibly separate.

Human control

The agent can investigate, propose, replay, undo, and export. It cannot approve enforcement.

Approval is deliberately absent from the WebMCP surface. The proposed contract remains visible and editable, and only the developer can activate it. This keeps the agent powerful at diagnosis while preserving human authority over a consequential runtime change.

How we built it

EmbedDoctor uses React 19, TypeScript, Vite, vinext, Tailwind CSS, and a framework-free boundary adapter. The demo contains a top-level checkout, an adopted payment iframe, and a same-origin sibling iframe communicating through real postMessage traffic.

One pure evaluator powers both report-only and enforcement modes, so the policy decision stays identical while only forwarding behavior changes. Incidents, scores, evidence IDs, comparison rows, and receipts are derived from captured events rather than assigned by demo phase.

Four seeded scenarios show that diagnosis changes with the evidence:

  • Perfect storm: lifecycle, protocol, and frame identity
  • Late listener: lifecycle only
  • Rolling upgrade: protocol only
  • Rogue sibling: source identity only

The exported bundle contains the contract, TypeScript runtime adapter, regression tests, evidence metadata, and migration notes.

Challenges

The hardest challenge was making a lifecycle race reproducible without inventing browser evidence. We replaced independent timers with a causal fixture: listener pending, early INIT, listener installation, retry, observed schema error, and then the sibling mutation.

A second challenge was proving why origin checks alone are insufficient. The rogue sender is deliberately same-origin, so it passes an origin allowlist. Only strict equality with the expected iframe's contentWindow catches it.

A third challenge was preventing a polished demo from becoming a predetermined animation. Every visible result now traces back to concrete event IDs, and a safety timeout can produce failure but can never manufacture a passing receipt.

Accomplishments

  • A complete developer experience, not only a tool-call proof of concept
  • A dramatic evidence-derived transition from 0/3 to 3/3
  • Five state-aware WebMCP tools with visible provenance
  • Developer-only approval and one-click undo
  • Scenario-dependent minimum contracts
  • A portable adoption bundle
  • Fifteen automated tests covering origin traps, source identity, schema and session validation, report/enforce parity, redaction, incident derivation, and export contents
  • A public deployment and reproducible open-source repository

What we learned

WebMCP is most compelling when a page exposes meaning, not DOM mechanics. The useful tools are not "click this button" or "read this panel." They are "inspect the selected evidence," "stage the smallest supported contract," and "replay this boundary." That semantic layer lets a person and an agent collaborate on the same live state while keeping actions observable and reversible.

What's next

Next, EmbedDoctor could package the boundary adapter as an SDK, support worker and popup channels, import production traces with privacy-preserving redaction, generate framework-specific adapters, and run verified contracts in CI. The broader goal is to make embedded web boundaries testable before intermittent failures reach production.

Honest scope

EmbedDoctor protects traffic adopted by a cooperating host and iframe. It does not inspect arbitrary third-party DOM, secure uninstrumented listeners, stop same-origin XSS, provide cryptographic authentication, or replace CSP and security review.

Built With

Share this project:

Updates

Submission history