DevNews

WebMCP site tools: a concrete read-only example

On this page
  1. The documented scope, checked September 8
  2. A complete example that changes no page data
  3. An annotation describes intent; it does not enforce it
  4. Integration checks that catch real mistakes

Site tools let a page expose operations to an agent working in the same browser session. OpenAI documents a subset of the proposed WebMCP standard. The implementation’s availability and limitations matter as much as the registration call.

The example registers an outline tool once, then reads current article headings on each invocation. A later heading edit changes the later result. The readOnlyHint annotation does not enforce the handler’s behavior.
The example registers an outline tool once, then reads current article headings on each invocation. A later heading edit changes the later result. The readOnlyHint annotation does not enforce the handler’s behavior. Chart : PeopleAreGeek. Data source.
View full-size image

The documented scope, checked September 8

OpenAI's site-tools documentation names GPT-5.6 Sol and Terra, with Luna disabled, and excludes Enterprise and Edu workspaces. Availability also depends on rollout and the current page. Its built-in browser does not discover declarative form tools or tools registered in iframes.

These limits describe that implementation, not every browser's interpretation of the evolving WebMCP proposal. A page can still offer its ordinary interface when an agent cannot use site tools.

A complete example that changes no page data

The following original example belongs in a page JavaScript module. It returns the current text of headings inside an article element:

if (typeof document.modelContext?.registerTool === "function") {
  await document.modelContext.registerTool({
    name: "read_article_outline",
    description: "Read this page's article headings without changing it.",
    inputSchema: {
      type: "object", properties: {}, additionalProperties: false
    },
    annotations: { readOnlyHint: true },
    execute: async () => ({
      headings: [...document.querySelectorAll("article h1, article h2")]
        .map(node => node.innerText.trim()).filter(Boolean)
    })
  });
}

The empty input schema is intentional: this operation needs no caller-supplied arguments. The handler queries the document when called, so it does not freeze the outline at registration time. On a page without matching headings, it returns an empty array.

This example does not register a tool on PeopleAreGeek merely because its code appears in the article. It is a code sample for integration into an application. It also does not prove that a particular account or browser will discover the tool.

An annotation describes intent; it does not enforce it

The read-only property of this example comes from what its handler does: read heading text and return it. It does not come from readOnlyHint itself. A malicious or mistaken implementation could attach that annotation to code with side effects.

Similarly, a schema constrains the intended input shape but cannot replace authorization and validation in the application's actual data path. Do not infer an automatic exemption from browser checks merely from an annotation.

Integration checks that catch real mistakes

Try the page with no WebMCP API, with an article containing headings and with an empty article. Then change a heading and call again: the result should reflect the current content. In a supported browser, separately confirm discovery and invocation.

For an iframe-based application, move the integration to an authorized top-level application boundary. Ordinary origin restrictions still apply; the top-level page cannot simply reach into an unrelated cross-origin frame because WebMCP is available.

Once an operation changes data, return enough information to verify the resulting state and reuse the same application permissions as the human interface. A small, accurately described action is easier to inspect than a broad tool whose side effects are unclear.

Refresh documented availability and limitations; correct readOnlyHint and iframe claims; supply a complete read-only example instead of an empty handler.