Skip to main content
Start with Build your first widget for a complete new project. In an existing Toolgrain server, the integration has three parts.

1. Define the HTML resource

Use resource() to return the HTML produced by your Vite build:
This file path assumes the server module lives in a server directory, as in the quickstart. The URI identifies the resource; the reader loads the file. Supply the HTML MIME type on both the definition and its returned content.

2. Point the tool at the resource

Add this field to your existing tool() definition:
The URI must match exactly. A tool can return ordinary JSON, which Toolgrain converts to a structured result and assistant-facing text. Use mcpResult() when you also need rich content or extra widget data.

3. Register both definitions

Pass the tool map and readonly resource list to your existing createServer() call:
Use the server’s normal stdio or HTTP transport, auth accessors, providers, and cancellation. A widget calls tools through its host; the browser does not need a second authenticated connection to the MCP endpoint.

Tool linking and visibility

For example, register a filter/refresh tool that the assistant does not need to discover:
Register it under an exposed key such as refresh_weather. Export that map’s type to React, then call useToolCall("refresh_weather"). A model-visible initiating tool supplies the first widget result. The host enforces visibility. Every call still needs the server’s usual authentication and application authorization. Keep registration static and provide useful assistant-facing results. Permissions and CSP go on the returned HTML’s _meta.ui, as the widgetUi object above shows. See permissions and metadata and the generic resources, tool results, and authorization guides.