WebMCP Security for Paid AI Actions: A Checklist That Holds Up
A tool schema helps an agent call your page. It does not authorize a purchase or protect private data. Use this checklist for validation, confirmation, origins, output trust, and cancellation.
A WebMCP tool looks reassuringly strict. It has a name, a description, a JSON Schema, and an execute callback.
None of those authorize the action.
The schema tells an agent how to call the tool. Your application still has to decide whether the current user may read the record, update the account, publish the page, or spend money.
The current WebMCP draft has a substantial security section covering prompt injection, misleading tool intent, privacy leakage, same-origin boundaries, and untrusted output. Paid AI apps add another concern: a model call may spend wallet funds even when it does not visibly mutate the page.
1. Keep authorization where it already lives
A WebMCP callback should call the same authorized application function as the normal interface. Do not create a second, weaker backend route for the agent.
Check the user session, resource ownership, server permissions, budget rules, and request limits on every call. Treat the schema as input documentation, then validate the actual values inside execute and again at the server boundary.
In an AI Pass app, OAuth authorizes model access for the connected user. WebMCP does not receive the token and should never return it.
2. Confirm consequences in plain language
A read-only hint is appropriate for an action that neither changes state nor spends money. A paid model request is not read-only.
The confirmation should name the action and the cost-bearing account in language a person can understand:
confirmation: ({ seconds }) => ({
title: 'Transcribe this recording?',
message: `Use your AI Pass wallet to transcribe ${seconds} seconds of audio?`,
confirmLabel: 'Transcribe'
})
Do not hide a charge behind "Continue" or bundle several consequences into a generic approval. If the action already has an equivalent confirmation in its normal handler, the WebMCP wrapper may defer to that one.
3. Expose less data
Give the tool only the parameters it needs. A summarize_selected_note tool needs a note ID or the selected note's text. It does not need the full notebook, wallet balance, OAuth token, file list, and user profile.
Return the smallest useful result. Update the visible page, then send the agent a status and the output it needs for the next step. Private prompts, credentials, raw authorization responses, and wallet details do not belong in tool output.
Over-parameterized tools create privacy leaks even when every field is technically valid.
4. Treat external output as untrusted
A search result, uploaded document, support ticket, or model response may contain text that tells an agent to ignore prior instructions or call another tool.
Set untrustedContentHint: true when a tool returns user-generated or external content. Keep the output as data. Do not concatenate it into a new tool description or system instruction.
This annotation is a signal, not a sanitizer. The agent and application still need prompt-injection defenses and narrow permissions.
5. Stay same-origin unless the product needs more
Chrome's WebMCP security documentation says the tools Permissions Policy defaults to self. Top-level pages and same-origin frames can use the API. Cross-origin frames need explicit delegation through allow="tools".
AI Pass keeps exposedTo unset by default. If a trusted iframe workflow requires it, list exact HTTPS origins. Do not use a wildcard for convenience.
Also keep the document origin isolated. Chrome disables WebMCP when a page opts out through settings such as Origin-Agent-Cluster: ?0.
6. Register tools only while they make sense
A stale tool can be as dangerous as an overpowered one. If delete_selected_layer remains registered after the selection changes, the agent and user may have different ideas about what "selected" means.
Register tools from current page state. Unregister them on route changes, component teardown, logout, or state transitions. Use an AbortSignal to connect tool lifetime to the application lifecycle.
Forward the execution signal into fetches and model calls. Cancellation should stop work promptly and avoid unnecessary spend.
7. Make the visible interface authoritative
The person should be able to see what the tool did. Put generated text in the editor, show the newly added object on the canvas, and render validation errors next to the relevant field.
WebMCP's advantage is shared context. A callback that changes hidden state and returns "done" throws that advantage away.
The ordinary interface must also remain complete when WebMCP is missing. This is both a compatibility requirement and a useful safety check: the agent channel should not become a secret administration panel.
8. Test intent, not only code coverage
Unit tests should cover registration, invalid schemas, cancellation, declined confirmation, successful execution, visible UI changes, and cleanup.
Agent evals need different prompts:
- a direct request that should call the tool
- a vague request that should trigger a question
- a nearby task that should use another tool or no tool
- hostile text returned by an untrusted source
- a request to act without confirmation
OpenAI's WebMCP demo suggests adding a feedback tool during development. That can be useful if it reports tool errors and unclear descriptions. Keep it out of production unless users genuinely need it.
Before you publish
- The normal page controls complete every exposed task.
- Each tool maps to one product action.
- The server repeats authorization and input validation.
- Paid or consequential calls ask for visible confirmation.
- Tool inputs and outputs contain no credentials or unnecessary private data.
- External text is marked untrusted.
- Cross-origin exposure is absent or limited to exact approved origins.
- Cancellation reaches network and model calls.
- Tool registrations disappear when their page state is gone.
- Direct, ambiguous, and hostile prompts have been tested.
If one item fails, narrow the tool before shipping. Remove unnecessary inputs and results, or split a broad action into smaller actions with clearer consequences.