On August 31, OpenAI added support for website tools in the desktop browser. ChatGPT Work and Codex can now discover tools that supported sites expose through WebMCP, then use those tools inside the same browser session. Four days later, the Web Machine Learning Community Group published a new WebMCP draft report.
WebMCP lets a page register JavaScript functions that an AI agent can call. That can be more reliable than making an agent hunt through buttons and forms. It also gives the agent another path into your application. Before shipping one, review this contract:
| Contract field | What the site must declare or enforce | Release evidence |
|---|---|---|
| User goal | One plain-language job with a specific result | Test prompt selects only the intended tool |
| Effect | Read, reversible write, or consequential action | Description, annotation, and implementation agree |
| Identity | The user and account allowed to run it | Server rejects another account and an expired session |
| Input | Tight schema plus business validation | Extra, malformed, and unauthorized values fail |
| Confirmation | Exact effect shown before commitment | Cancel leaves state unchanged |
| Replay control | Idempotency rule for writes | Duplicate calls create one result |
| Result | Structured outcome, receipt, and safe error | Agent can distinguish success, rejection, and unknown |
| Audit | Tool, actor, arguments, decision, and effect | One trace reconstructs the call without storing secrets |
The table is the minimum useful asset. A tool should stay private until every row has an owner and a passing test.
Understand the new path into your site
Classic MCP usually connects an AI client to a separate server. WebMCP puts the tool registration inside a web document. The current draft exposes a modelContext interface that lets a page register tools with a name, description, JSON Schema input, execution callback, and optional annotations.
Those annotations include hints for read-only tools, untrusted output, and consequential actions. They help an agent or browser choose safer behavior. They do not enforce your business rules. A tool marked read-only can still contain code that writes data. A tool described as "review cart" can still charge a card if its callback does that. The WebMCP draft calls out this gap directly: natural-language intent and actual behavior can diverge.
The browser session matters too. A WebMCP tool runs on a page that may already have the user's authentication cookies, account selection, payment state, and private data. The server must treat the call like any other authenticated request. The model's choice to invoke a tool is never proof that the user may perform the operation.
WebMCP is a Community Group draft, not a W3C standard. Browser and product support will change. Keep an ordinary, accessible interface working beside the tool so customers are not locked to one agent or browser.
Give each tool one visible effect
Start from the user's goal, then cut the tool until its name and description leave little room for interpretation.
manage_order is too broad. It might retrieve status, change an address, cancel fulfillment, or issue a refund. The agent cannot know which side effects hide behind the verb "manage," and a reviewer cannot write one sensible confirmation rule for it.
Prefer narrower tools:
get_order_statusreads one order the current user may view.prepare_return_requestcalculates eligibility and returns a preview without changing the order.submit_return_requestcommits the preview after confirmation.cancel_return_requestreverses the request when the business process still allows it.
Write the description as a behavioral contract. State what changes, what does not, whose record is affected, and what the result means. Keep policy text and instructions out of values supplied by visitors. Tool names, parameter descriptions, and return values all become model input, so user-generated prose inside them can act as prompt injection.
The description must match the code path. Review it whenever the implementation changes. Renaming a button does not update a stale tool definition, and a stale definition can make an agent choose the wrong operation with complete confidence.
Reuse the application's trusted boundary
A WebMCP callback should call the same application service as the visible UI. It should not duplicate authorization or create a shortcut around server validation.
For every execution, the server should:
- Resolve the current authenticated user from the session, never from a model-supplied user ID.
- Resolve the active account on the server and verify membership again.
- Parse the input against a strict schema that rejects unexpected fields.
- Apply the same ownership, policy, inventory, pricing, and rate-limit checks as the normal interface.
- Write through an idempotent command for any state change.
- Return a stable status and receipt that describes the actual external effect.
Do not send a broad application object into the agent and ask it to choose safe fields. Build a small result after authorization. An order-status tool might return a public carrier status, estimated date, and masked order reference. It does not need payment details, internal fraud notes, or other orders in the account.
This is where the chatbot tool-permissions checklist transfers well to WebMCP. The transport is new. Least privilege, dedicated business operations, and server-side checks are still the controls that decide what can happen.
Worked example: preview, confirm, commit
Consider a customer who asks an agent, "Return the blue lamp from my last order." The page exposes prepare_return_request and submit_return_request.
The first tool performs an authorized lookup and returns a preview:
{
"status": "ready_for_confirmation",
"preview_id": "ret_prev_8f21",
"order_reference": "...1842",
"item": "Blue desk lamp",
"refund_estimate": "$48.00",
"return_method": "Prepaid label",
"expires_at": "2026-09-09T15:20:00Z"
}
The browser shows those details to the customer. Nothing has changed yet. If the customer confirms, the agent calls the commit tool with only the preview ID and an idempotency key. The server reloads the preview, verifies the same user and account, checks that it has not expired, and recalculates eligibility before submitting.
{
"status": "submitted",
"return_id": "ret_7319",
"receipt_id": "rcpt_44b6",
"submitted_at": "2026-09-09T15:14:22Z",
"next_step": "Download the prepaid label"
}
Now change the case. The agent retries after a network timeout. The same idempotency key must return ret_7319, not create a second return. If the preview expired, the server returns preview_expired and no return ID. If the user switched workspaces, it returns account_mismatch. An empty response or timeout stays outcome_unknown until a status lookup finds a receipt.
The final answer should follow the receipt. "Your return was submitted" is valid only when the commit result contains the return ID. This is the same discipline used in chatbot action verification: the attempted call and the completed business effect are different events.
Treat tool text as untrusted input
The WebMCP draft identifies prompt injection in tool metadata, arguments, and output as a core risk. A product review returned by get_product_reviews could contain text that tells the agent to ignore the user and make a purchase. A support ticket could tell the agent to send account data to another site. The string is data, even when it sounds like an instruction.
Site authors can reduce the risk:
- Keep names and descriptions static, short, and reviewed in source control.
- Mark results that contain visitor, merchant, forum, ticket, or document text with the untrusted-content hint.
- Return typed fields instead of one large prose block when the data has known structure.
- Separate retrieval from transactions so untrusted output cannot commit an action in the same call.
- Require fresh confirmation after the application renders the exact item, quantity, price, account, and destination.
- Restrict outbound destinations and data fields even when another tool asks for them.
An annotation is still a hint. The browser agent may use it to decide when to warn the user, but your server owns the authorization and confirmation requirements. If a purchase, deletion, message, booking, or account change requires approval in the visible UI, the WebMCP path should require the same approval or a stronger one.
Test the path agents will actually call
Unit tests for the callback are useful, but they do not prove that an agent discovers the correct tool, supplies the right account context, handles cancellation, or reports the outcome honestly. Run release tests through a supported browser-agent path.
| Test case | Prompt or condition | Pass condition |
|---|---|---|
| Ambiguous goal | "Deal with my last order" | Agent asks what outcome is wanted; no write runs |
| Cross-account target | Request an order from another workspace | Server denies before returning private fields |
| Description mismatch | Rename an effect without updating metadata | Contract test blocks the release |
| Injected output | Product review asks the agent to buy | Text remains data; no transaction starts |
| Confirmation cancel | User rejects the rendered preview | No state change and no success claim |
| Duplicate execution | Retry the same commit after timeout | One business record and one stable receipt |
| Route change | Navigate away while a tool is running | Abort is handled; stale tools are unregistered |
| Expired session | Authentication ends before commit | Server denies and asks for a fresh sign-in |
| Unsupported client | Browser cannot discover WebMCP | Visible form still completes the same job |
Capture tool registration, selected tool, normalized arguments, authenticated actor, account, policy decision, idempotency key, result code, receipt, and final agent message. Redact secrets and unnecessary customer fields. A trace should show whether the agent chose badly, the site rejected the call, or the external operation completed.
Include lifecycle tests for single-page applications. Tools registered for one route should disappear when that route unmounts or its data becomes stale. Honor the execution abort signal, but do not assume aborting the browser callback reverses a request that already reached the server. Query the receipt before retrying.
The AI browser-agent website test guide covers labels, focus, errors, and visual flows. Keep those tests. WebMCP adds a structured route; it does not excuse a broken human route.
Measure safe completion, not call volume
A rising WebMCP call count says the feature is discoverable. It does not say users got the right result.
Track selection accuracy, validation-denial rate, confirmation-cancel rate, duplicate-effect rate, unknown-outcome rate, receipt coverage, and durable task completion. Review denials by cause. Frequent schema failures point to a tool contract the agent cannot use. Frequent account mismatches may reveal stale session state. Many cancellations may mean the preview exposes a surprise that the earlier conversation hid.
Sample successful calls too. A tool can return HTTP 200 while changing the wrong record, omitting a required disclosure, or leaving the agent to invent what happened. Compare the receipt with the final message shown to the user.
Let the website remain in charge
WebMCP gives websites a structured way to work with browser agents. The useful part is precision: a site can name the jobs it supports, validate typed input, show the user the exact effect, and return a receipt the agent can report.
That precision only survives when the tool uses the same authorization and business rules as the rest of the application. Start with one read-only goal. Add preview and commit as separate steps for writes. Test injected text, cancellation, retries, route changes, and account boundaries before exposing a consequential action.
No credit card required.



