Skip to main content
widgentic has always had two authors who never met on one screen: an agent that learns the authoring contract over MCP and drafts JSON, and a person who imports that JSON into a designer, fixes it and saves. WebMCP — an experimental W3C standard shipping in ChatGPT Desktop’s browser and in the Chrome 149+ / Edge 150 origin trial — lets a page register tools the browser’s agent calls under the person’s own session. @widgentic/webmcp registers the designers as those tools.
Beta. The API may change in minor versions before 1.0, and browser support is moving. Built against the specification’s document.modelContext shape.

One call after mounting

Sources are getters, resolved on every tool call, because hosts remount designers when the person switches tabs. A getter may bring its section on screen first — then “the agent asked for the theme designer” is something the person watches happen. In a browser without a model context the call resolves with supported: false, registers nothing and throws nothing.

The loop

  1. The person opens the authoring page in ChatGPT Desktop’s browser (or a flagged Chrome) and asks for a widget.
  2. The agent calls widgentic_widget_draft_get to see what is open, then widgentic_widget_draft_load with a definition. The designer validates it exactly as its Import panel would: applied, with the designer’s diagnostics — or refused, with the designer’s own error strings.
  3. Fix, restyle, ask again: example data (widgentic_widget_example_data_set), preview theme (widgentic_widget_theme_set), a theme entry, a shared schema, an action.
  4. The person saves. No tool persists anything; the host’s save controls remain the only write path. On the MCP endpoint’s next render_widget, any agent with a key renders the widget the two of them made.

The tools

Fourteen tools under a configurable prefix (default widgentic); only the designers you supply a source for get tools, the three reference tools are always present. Every editing tool’s description carries a summary of the template DSL and the style rules, and points at the guide and the check tool, so the agent drafts by the designer’s own rules from the first call. Read tools carry annotations.readOnlyHint, so agents run them without a confirmation step. Every result is MCP-shaped text content carrying one JSON document with a boolean ok. Refusals are results, never rejections: NOT_MOUNTED, INVALID_INPUT (naming the argument) and REJECTED (with the designer’s errors).

What the host’s agent can still do

No tool here saves. The guide and every editing tool tell the agent to leave the Save control to the person unless asked. A host whose agent can operate the page — ChatGPT’s browser can click elements — may press Save itself, under the person’s session and the host’s permission settings; asked to “create a widget”, ChatGPT drafted through the tools and then clicked Save. The package cannot prevent that and does not try: the draft is visible in the designer before any such save, and the person’s wording decides (“draft it and stop” versus “create it”). If that matters to your users, say it in your UI.

Browsers, flags and polyfills

  • Native: document.modelContext (the specification, ChatGPT Desktop) is resolved first, navigator.modelContext (Chrome origin trial) second; an explicit { modelContext } option wins over both.
  • Chrome / Edge without a token: chrome://flags/#enable-webmcp-testing, or --enable-features=WebMCPTesting,DevToolsWebMCPSupport and navigator.modelContextTesting.getTools() / executeTool() for driverless checks. With an origin-trial token on your page, no flag is needed on your origin.
  • Polyfills: nothing is bundled — a polyfill supplies the API, not the agent, and cannot make Firefox or Safari agent-capable. To reach extension-based agents, load one such as @mcp-b/webmcp-polyfill (it installs document.modelContext and defers to a native one) before exposeDesigners; the resolver finds whatever the page has.
Tools register on the top-level page only; browsers do not read tools from iframes.

Your own tools

registerTools(tools, { modelContext?, signal? }) registers any descriptors in the same shape under one abort signal, and exposeDesigners takes extra ones as { tools }. designerTools(sources, { prefix }) returns the descriptors without registering. Build results with okResult() / failResult() so agents see one vocabulary. The self-host example (Self-hosting) is the reference host: its authoring page registers the tools, and its web service can forward /mcp so one origin serves both surfaces.