Skip to main content
The quickstart’s server/index.ts has one place to configure the widget:
Edit that object as the widget needs more capabilities. Import AppResourceMeta as a type from @toolgrain/protocol/apps for autocomplete and field checking.

Request a permission

For example, a widget that copies a value to the clipboard can request:
Use empty objects, such as { clipboardWrite: {} }, rather than booleans. Other permission names are camera, microphone, and geolocation. Request only the permissions your widget uses. A declaration asks the host for access; the host can deny it. Check the browser API is available and handle permission denial in the widget’s interaction handler.

Allow network requests and external assets

If the React code itself fetches a remote API, add its origin:
connectDomains covers fetch, XHR, and WebSocket connections. resourceDomains covers external scripts, styles, fonts, images, and media. Use explicit origins, not paths to individual API methods or images. The host may restrict them further. The quickstart bundles its JavaScript/CSS into HTML and needs no external origins. Calls made with useToolCall travel through the host; add a network origin when your widget makes the network request itself.

Put settings on the returned HTML

The widgetUi object belongs on each resource content item’s _meta.ui. The quickstart already places it here:
Here, builtHtml is the string read from your built widget file. Putting permissions/CSP on the tool, or only on the outer resource-read result, does not configure the widget sandbox.

Resource metadata

Omitted network/frame origins do not allow arbitrary connections or nested frames. The default base URI is restricted to the sandbox’s own origin. A domain request does not configure DNS, host allowlists, or OAuth callbacks. Recheck domain/permission behavior for the host you target; the acceptance record lists what was actually exercised.

Three kinds of metadata

See tool linking and visibility for app-only refresh/filter tools.

Extra widget data

Use mcpResult() when the tool also needs result metadata. For example, replace the weather tool’s execute function and import mcpResult from @toolgrain/mcp:
React receives the full envelope, including the inferred metadata type:
Keep result _meta optional in your component: errors or protocol conversion can omit it. Continue returning meaningful content for the assistant. Shared entries can use an application-owned marker such as _meta.view for routing.

Connection and authorization

The host owns iframe creation, sandboxing, CSP enforcement, and permission grants. Toolgrain’s browser connection accepts messages from the embedding parent and validates known wire envelopes. hostOrigin can restrict that parent to an exact origin; hosts using opaque sandbox origins may need the default setting. Permissions, capability claims, and routing metadata do not establish identity or authorize server work. Preserve endpoint authentication and application authorization for tool calls and resource reads. Never put bearer credentials or server services in widget HTML. Use import type for the tool map and validate application data when your UI requires it. The reviewed Apps resource contract defines the wire fields.