Guides
Let the assistant use your page
Publish what your page already does — look up an order, book a slot, start a return — as actions the assistant runs, asking first before changing anything.
On this page
AI Assistant already knows what your business says. Page tools let your assistant do what your page does — check an order, reserve a slot, begin a return — by calling functions your site already has, in the visitor's own session. Write each action once: it reaches every visitor, over WebMCP where the browser supports it and the assistant's own bridge elsewhere, apps included.
Your assistant is already on the page, from the embed script you added at setup. Page tools ride that same script — nothing extra to install.
1. Decide what the page can do
Pick three to seven things a visitor does here, noting whether each only reads or changes something.
| Reads | Changes |
|---|---|
| Look up an order, check stock, show today's slots | Book, pay, cancel, submit a form, change an address |
Name each with a verb — check_order_status, start_return — and describe it as you would to a new colleague; that description is what the assistant reads to decide when to use it.
2. Register them
One call, where those actions live:
// One call, both transports: the browser's own WebMCP where it exists,
// and the assistant's bridge everywhere else (Safari, Firefox, app WebViews).
BusymateAI.registerPageTools([
{
name: "check_order_status",
description: "Look up an order by its number and say where it is.",
inputSchema: {
type: "object",
properties: { orderNumber: { type: "string", description: "The order number, as printed on the receipt" } },
required: ["orderNumber"],
additionalProperties: false,
},
annotations: { readOnlyHint: true },
execute: async ({ orderNumber }) => (await fetch(`/api/orders/${orderNumber}`)).json(),
},
]);execute runs in your page, on the visitor's own session — the assistant never receives your cookies, tokens or markup, only what you return.
Mark every read with annotations: { readOnlyHint: true }. Anything unmarked counts as a change: the assistant shows the exact call and waits for a yes, with no way off.
Give every argument in inputSchema.properties a one-line description — the assistant reads it to decide what to pass, and one with none is a guess. Each tool validates independently: a real mistake (a bad name, no execute) is logged with the exact field and excluded while the rest of the call registers; a missing description registers with a console warning naming it.
With a bundler, import registerPageTools from /sdk/v1/webmcp/index.js on your assistant's address instead of the global.
3. Forms you already have
If the action is a real <form>, annotate it and register every annotated form with one call to registerDeclarativeForms() — no other JavaScript:
<form action="/book" toolname="book_appointment"
tooldescription="Book an appointment for a date, a time and a service."
toolautosubmit>
<input name="date" type="date" toolparamdescription="The day, e.g. next Tuesday">
<input name="time" type="time" toolparamdescription="The start time">
<select name="service" toolparamdescription="Which service to book">
<option>Consultation</option>
<option>Follow-up</option>
</select>
<button type="submit">Book</button>
</form>The form keeps working as before. Submitting changes something, so it asks first — unless you add data-tool-readonly to a form that only filters what is on screen.
4. Ask with a form, not a list
When an action needs details the visitor has not given, return a form card
rather than asking in prose — and register sign_in when something needs their
account, so they never leave the conversation to log in.
Forms and sign-in inside the chat has both contracts and a
copy-paste example.
5. Tools that come and go
A tool the visitor cannot use should not be offered. Pass { signal } from an AbortController and abort() when the view goes away.
6. Who can see them
Tools are exposed only to your assistant's own address by default; any other origin is refused by name. Add one by naming it exactly in exposedTo — no wildcards, since *.example.com would hand every subdomain the right to run your actions.
Site page tools, under Channels and access, is about your VISITORS: turn it off and the Site tools sheet stops appearing, without a site change.
Assistant may operate the host page, under Integration › Page tools, is about the ASSISTANT:
| Setting | What the assistant may do |
|---|---|
| No | Never calls your actions; visitors can still run them from the Site tools sheet. |
| Read-only actions | Looks things up — an order status, a cart — but changes nothing; a changing tool is refused before it is offered, and the assistant says plainly it can read but not act. |
| All actions, with confirmation | Also runs changes, each confirmed with the visitor in chat first. |
New workspaces start at All actions, with confirmation — safe, since nothing is reachable until your page registers a tool naming your assistant in exposedTo. The panel takes allow/deny lists by tool-name prefix (blocking wins) and logs every attempt.
7. Let a checker see them
The SDK writes <link rel="webmcp-catalog" href="…"> into your head, rewritten
whenever your tool list changes, so an inspector can confirm registration
without a console. With a server, serve that document at a real URL and link it
from your served head — the only version a reader sees without running the page.
Verify
- Open your site and press Site tools — every tool is listed with its description, arguments and read-only mark.
- Run a read-only tool from it; the result matches what your page shows.
- Run one that changes something: it asks first, showing the exact call; declining leaves the page untouched.
- Ask the assistant in plain words — it picks your tool rather than describing a page.
- Open the page in Safari or your mobile app: the list is identical, the bridge covering what the browser does not.
- Navigate away from the view you registered on: the tool leaves the list.
- View the page source: a
webmcp-cataloglink is present and lists the same tools.
Next
- Forms and sign-in inside the chat — cards a tool asks with, and in-chat sign-in.
- Connect your MCP server as assistant tools — actions on your servers rather than the page.
- Recognize signed-in customers — so a page tool can answer about this customer's order.
Questions
Do I need Chrome for this to work?
No. Where the browser implements WebMCP your tools register with it; everywhere else — Safari, Firefox, any iOS or Android WebView — the assistant uses its own bridge. You write them once either way.
Can the assistant run something without asking?
Only what you marked
readOnlyHint. Everything else stops at a confirmation showing the exact call and arguments, until the visitor agrees.What can the assistant see?
Only what your
executereturns — never your session, storage or markup, and treated as content rather than instructions, so page text cannot redirect it.Can another site use my tools?
No. They are exposed to an exact list of origins — your assistant's address by default — and a call from elsewhere is refused by name, not ignored.
I already wrote the browser API by hand. Do I have to change?
No. The one call registers on that browser API where it exists and adds the bridge where it does not, so the reason to switch is reach, not correctness.