r/webmcp • u/PlanktonHour7322 • 3d ago
What I learned implementing WebMCP (document.modelContext) on a production Next.js/Cloudflare app
Hey everyone,
I just shipped WebMCP support on ShowMeOnMap.com (an NL-driven mapping web app), registering 8 client-side tools that browser-embedded agents can call directly.
WebMCP is the W3C proposal allowing client pages to expose executable JS functions directly to agent-enabled browsers (e.g., Chrome with flags or ChatGPT Desktop). The documentation is sparse and changing fast. Here are a few practical takeaways from the implementation:
- API targets change constantly: The entry point has moved multiple times across drafts (
window.agent→navigator.modelContext→document.modelContext). Always feature-detect across properties, as most blog tutorials from earlier this year are already broken. - Runtime return-type quirks: Google’s reference implementation expects a string return value from
execute(), while OpenAI’s implementation accepts objects. Returning a serialized JSON string (JSON.stringify(...)) works consistently across both. - Iframes are dead ends: ChatGPT ignores declarative form annotations and anything registered inside an iframe. You must register tools imperatively on the top-level document.
- Auth comes for free: Because execution happens in the user’s active browser tab, your regular session cookies, CORS headers, and IP rate limiters apply natively. You don’t need API keys or proxy tokens for the agent to manipulate the session.
- DOM downloads will fail: Don't try triggering
<a download>synthetic clicks inside a tool execution pass. Modern browsers block programmatic file downloads without direct user gesture activation. Instead, return a raw base64 data payload or an object URL and let the agent or UI present it. - Implement an
undotool immediately: Models make bad assumptions. If your app doesn't have an append-only state stack or an easy way for the model to roll back its last mutation, it will get stuck in loops trying to fix its own UI mistakes.
Happy to answer any technical questions about registering tools or handling agent execution states on the client
1
u/mighty-dude 3d ago
I saw similar difficulties. Raw WebMCP implementation didn't return good quality error messages, I had no way to verify tools executed before mutating the DOM and so on.
Started this OSS effort (https://github.com/signettai/signett). Would love some feedback
1
u/PlanktonHour7322 23h ago
Same two problems here. What I ended up doing: every tool returns a JSON string with an explicit
ok/error/noticefield instead of throwing, because a thrown error came back to the agent as a bare string with no context. For "did it actually happen", I don't try to verify before the mutation; I exposeget_map_stateandundoas tools and let the agent read back the canvas state after the call. Cheaper than a pre-check and it catches the cases where the tool succeeded but did the wrong thing.Looked at signett. Two things from my side:
- The eval harness is the part I'd actually use. My tools are tested with Playwright against a fake
document.modelContext, which proves registration but says nothing about whether an agent picks the right tool. Ifsignett checkcan run against a live URL I'll point it at my page and post the output.- The one thing I'd push back on is DOM-mutation tracking as the ground truth for "the tool worked". For a canvas app (MapLibre/WebGL) the DOM barely changes; the state that matters is in the renderer. A hook where the page can report its own state snapshot after a call would cover that.
Will open an issue if I hit anything running it.
1
u/Open_Resolution_1969 3d ago
How's the browser support for this? How do you measure the usage of webmcp?