Inspiration

WebMCP lets a site hand an agent typed functions instead of a page to scrape. The limit shows up immediately: document.modelContext is per document. The agent sees the page it is on and nothing else, while every task I actually wanted spanned sites. Find the delayed orders here, open a ticket there, email me a summary.

Then the less comfortable realisation: agents could already do that. They browse, they navigate, some remember. What was missing was not capability.

What it does

The extension is three parts, and only the last is impossible outside a browser extension:

  • Discovery : a modelContext polyfill installed in the page's MAIN world at document_start, or a native implementation wrapped in place, mirroring every registration out to the service worker.

  • Registry: one list across tabs and sessions: live page tools, remembered sites that are closed right now, and nine action tools of its own, each with a status (AVAILABLE, SITE_CLOSED, AUTH_REQUIRED, TOOL_CHANGED, TOOL_MISSING). A public crawler can catalogue which sites expose tools, but it is always signed out, so it never sees the ones behind your login.

  • Cross-site execution: the extension runs each step on the site that owns that tool, in your own logged-in tab.

The site exposes 13 capabilities of its own through registerTool(), and is where a run stops being something that happened and becomes something you can repeat: every step the agent took, the capability each one used, and a button that runs the whole thing again.

Reach on one side, certainty on the other.

What I actually built

Not a smarter agent, a layer that makes an agents actions accountable and repeatable.

Four things it refuses to do:

  • Refuses to invent. A fabricated capability is rejected with the real names listed.
  • Refuses to self-approve. The write prompt takes no approved argument an agent could set for itself, and fails closed where it cannot ask.
  • Refuses to guess. Where judgement is needed, a reason step stops and hands the question back with the data attached. A gate fails closed rather than compare against data that never arrived.
  • Refuses to take the agent's word. The engine writes the run record, so a step marked ok genuinely ran.

Steps are JSON only, never generated JS, validated, then checked against the registry.

Challenges I ran into

Half of real WebMCP tools navigate instead of returning data. Pointed at real commerce sites, I found tools that move the browser rather than return values ,and a navigation drops that tab's tools from the registry, so a site read as "closed" seconds after its own tool had run.

The agent may bypass you entirely. One posting straight to the extension's page API got a run id back while nothing was saved. Recording had to become a property of the bridge rather than of how a prompt was phrased, because you do not control the prompt.

What I learned

Magpie is not a new capability. Neither was WebMCP. Agents operated websites long before the spec scraping the DOM, driving a mouse. What WebMCP added was a contract: the site declares what it supports, with types, instead of the agent inferring it from markup. This project does the same thing one layer up, a contract across pages rather than within one.

What's next

Watch jobs, where the hard part is not the timer but pre-approving a write with limits validated in code rather than at a prompt. Remote MCP servers feeding the same registry. And a manual builder, so aworkflow can be assembled from proven steps with no agent involved at all.

Built With

Share this project:

Updates

Submission history